Flutter Home

Flutter Development

You forgot everything again didn’t you 🙂

OK let’s try to get you back up to speed quicker this time.

Go through the install process if you’re really starting fresh. Make sure you’ve got the various plugins installed in vscode and you’re ready to go.

Other wise do flutter upgrade to get things to the latest.

Before you try digging into old projects, code some simple apps again to get refreshed on stuff.

Create a new app flutter create todo or flutter create --org run.cgrant todo

Try to make a super simple todo list with no persistance.

Hints:

  • Column
  • Text field
  • Button
  • ListView

1 Basics

Flutter has a quite in-depth install process since it’s dependent on xcode and android studio.

Once installed create a new app with

flutter create flutter_contacts
cd flutter_contacts

Open this with android studio

Before getting into the coding lets refresh on the core concepts

Key Files & Folders

the core source files are under /lib

Typically there’s a minimal main.dart file

the main config file is /pubspec.yaml

  • Contains the package name of this app
  • Contains dependency definitions

Packages and structures

Files can reference each other with standard paths following the package name.

Assuming the following structure

flutter_my_demo
- pubpsec.yaml (name: flutter_my_demo)
- lib/
    - main.dart
    - screens/
        - homepage/
            homepage.dart

You can access the homepage dart file with:

import 'package:flutter_my_demo/screens/homepage/homepage.dart';

Folder structure convention

Generally apps seem to break up the folder structure like so:

lib/
- main.dart
- routes.dart
- screens/
    - screen_name
        - index.dart
        - widgets
            - widget_name
                index.dart
- widgets/ 
    - widget_name
        index.dart
- util/
- models/
- services/

This structure provides app level widgets and screen level widgets which helps keep things organized.

the routes.dart file contains the routes of your application and imports all screens.

Code Basics

the main.dart file executes the app with the following convention

void main() => runApp(MyApp());

MyApp() is a class that extends either a StatelessWidget or StatefulWidget. In general if the content of the screen is not going to change its display it should be stateless. StatfullWidgets require additional code we’ll review in a minute.

StatelessWidget

the basic class definition is simple

class MyApp extends StatelessWidget {

}

We’re going to override the build method for the Stateless Widget and return our main display.

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    
    return ...
  }
}

specifically what we’re going to return is another widget, any widget, but in this case a special Widget called MaterialApp that provides a material header theme look and feel. It takes parameters for title, theme and home

MaterialApp(
      title: 'Flutter Demo',
      theme: themeData(
        primarySwatch: Colors.blue,
      ),
      home: ...  ,
    );

And you guessed it, home refers to another widget, any widget, in this case it will be our custom homepage screen.

Here’s the full class code:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Welcome to Flutter'),
        ),
        body: Center(
          child: Text('Hello World'),
        ),
      ),
    );
  }
}

StatefulWidget

Stateful widgets require a second class to take care of the state management. That second class extends the State component defining the type of the class it’s going to manage.

The StatefulWidget class is, itself, immutable and can be thrown away and regenerated, but the State class persists over the lifetime of the widget…Much like a stateful Kubenetes workload has a pod and a stateful disk. The pod can go away but the disk remains

class MyHomePage extends StatefulWidget {...}
class _MyHomePageState extends State<MyHomePage> {...}

The main class uses that State class by defining it through the createState() function

class MyHomePage extends StatefulWidget {
    @override
    _MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {...}

the state class can alter the state of the main class by calling the setState() function, which in turn calls the build() method to repaint the display

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return ...
  }
}

Classes & Constructors

class Person {
  final String first;
  final String last;
  final String email;

  Person : first = "none"; // initializer list  assigns variables before the constructor runs
  Person(n) : first = n { print(n) } // Initializer with constructor (note {} replaces the ;)
  Person(this.first) // automatic assignment to instance var in constructor
  Person({this.first}) // curly braces make the value optional
  Person.myName(this.first) // Named constructors just provide extra clarity 

  //example
  Person.fromMap(Map<String, dynamic> map, {this.email}) // Map<Key, Value> dynamic == various
      : assert(map['first'] != null),
        assert(map['last'] != null),
        first = map['first'],
        last = map['last'];
 

}