Flutter Home
Table of Contents
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'];
}