An Introduction To Flutter

The crowded mobile app framework landscape recently welcomed a new member — Flutter.

Kenneth Carey
7 min readMay 22, 2020

Flutter promises cross-platform, natively compiled apps, with slick smooth UIs. Sounds promising. Developed by Google, the framework is gaining in popularity, especially amongst new startups.

Single Codebase…like Java?

Flutter’s major selling point is that it allows developers to create mobile apps for Android and iOS using a single codebase. It’s possible to build a Flutter app targeting Android and build the same project on a Mac for iOS devices without changing a single line of code.

Unlike most other mobile app frameworks Flutter does not use WebView nor OEM widgets. Instead, Flutter uses its own rendering engine to draw widgets.

The Crowded Framework Landscape

Apps are natively compiled too, so you’ll need a machine with Android SDK installed for targetting Android and you’ll need to be running XCode to build for iOS devices.

So does it use Java, Swift, Kotlin, Javascript, CSS…?

The Flutter team opted for Dart, an object-orientated language which can compile to ARM & x64 machine code for mobile, desktop, and backend. It can also compile to JavaScript for the web. App developers use Dart to create the UI and business logic — no visual designers or screen layouts stored as XML. Everything is coded in Dart.

Below is a minimal flutter app, where the entry point of the application main() calls the function runApp() which accepts a Widget as a parameter.

import 'package:flutter/widgets.dart';

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

class MyApp extends StatelessWidget {
@override
Widget build(context) => Center(
child: Text('Hello Flutter!', textDirection: TextDirection.ltr)
);
}

Widgets are the building blocks of a Flutter UI. You pass a root widget to the runApp function and that widget creates child widgets and so on… forming a hierarchy of widgets.

There are two types of Widgets in Flutter : StatelessWidget and StatefulWidget (I’ll explain the differences later). In this example, the class MyApp IS-A StatelessWidget and overrides the build method to create two widgets - a Center widget and a child Text widget. In Flutter, the root widget automatically fills the screen, allowing the Text widget to be centered on screen.

Getting Started

You’ll find step by step install instructions for installing Flutter at flutter.dev. Allow about 1 hour to get through the various installations and verifying your setup. For this blog series, we’ll be developing Android apps on Windows 10 using Visual Studio Code.

I highly recommend running flutter doctor from the command line before proceeding. You should see output like this (Windows OS):

Time for Another ‘Hello, World’ App

We’re going to create and run a very basic Flutter app, in Visual Studio Code firstly and then using the Flutter CLI.

Visual Studio Code

  1. Open Visual Studio Code and select View->Command Palette. Enter flutter new followed by a project name.
VSCode Command Palette

2. You’ll then be prompted to select a directory to create the project in.

VSCode Project Folder

3. After a few seconds, you’ll be presented with a project structure like below:

VSCode Project Structure

Flutter CLI

Flutter comes with a CLI with commands for creating new projects, running flutter apps, upgrading flutter and many more.

  1. To create a new project from the command line enter flutter create <app_name> from any directory.

If the command fails for not being recognised as internal command, then check your PATH environment variable is pointing to your flutter bin directory.

Flutter CLI will auto-generate the same files and directories shown above. Type flutter create -help to see more options when creating a new project.

2. Switch back to VS Code and select File->Open Folder and browse to the directory you ran the flutter create command from.

Running Your App

flutter create creates a sample counter app which you’ll find in libs/main.dart.

  1. Delete the contents of that file and paste in the minimal flutter app from above.
  2. Select Run->Start Debugging (F5) and you’ll be asked to select a device. If you followed the flutter.dev installation instructions closely there should be a simulator or your own Android device listed. If not, jump to here and follow the steps listed.
‘Hello, Flutter’ Android App

On Stateful and Stateless Widgets

Flutter UIs are a hierarchy of widgets, of which there are two types: StatelessWidget and StatefulWidget. Stateless widgets are immutable - their properties can’t change, in other words - all values are final. Stateful widgets maintain state that might change during the lifetime of the widget. When that state changes the widget is re-built.

Let’s take the example of the simple Text widget. Our minimal app above displays the text ‘Hello, Flutter’. We passed that text in the constructor of the Text widget and can’t change it after the widget is created. The Text widget is stateless - it has no State object that the Text widget can bind too.

At this point, you might be wondering what Flutter widget do I use to display dynamic text? You’ll still use the Text widget but you need to wrap it in a StatefulWidget.

Text widget “binding” to State field

A StatefulWidget Example App

Let’s build an app consisting of two Text widgets and a button. The Text widgets are initially blank. When the user clicks the button the Text widgets should display a user name and role.

  1. Create a new Flutter app named ‘login_user’. Open main.dart, delete the contents.
  2. Paste in the code below
import 'package:flutter/material.dart';

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MyUserPage();
}
}

class MyUserPage extends StatefulWidget {
MyUserPage({Key key}) : super(key: key);

@override
_MyUserState createState() => _MyUserState();
}

class _MyUserState extends State<MyUserPage> {
String _userName = "";
String _userRole = "";

void _updateUser() {
setState(() {
_userName = "Homer";
_userRole = "Sector 7G";
});
}

@override
Widget build(BuildContext context) {

return WidgetsApp(
builder: (context, int) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'$_userName',
style: Theme.of(context).textTheme.headline4,
),
Text(
'$_userRole',
style: Theme.of(context).textTheme.headline6,
),
RaisedButton(
onPressed: _updateUser,
child: Text(
'Login',
textDirection: TextDirection.ltr,
),
),
],
),
);
},
color: Colors.blue,
);
}
}

3. Run the project by pressing F5 in VSCode or by dropping to the command line and entering flutter run.

4. After the app launches on your device or simulator click the Login button. You should see the two Text widgets update.

Flutter App with Stateful Widget

The entry point of the app main() is similar to the minimal app from earlier. It calls the runApp() function which is passed a StatelessWidget called MyApp. Take a closer look and you’ll see that the build() function is returning a new widget called MyUserPage - a StatefulWidget.

Think of State as information. In our example above userName and userRole are pieces of information which are going to change over the lifetime of the widget.

To implement a Stateful widget you need to create two classes: a StatefulWidget class and a State class. The State class is where the app’s logic and state resides — it maintains the state for the MyUserPage widget. State objects are created by the Flutter framework by calling the createState method.

class MyUserPage extends StatefulWidget {
MyUserPage({Key key}) : super(key: key);

@override
_MyUserState createState() => _MyUserState();
}

The Column widget is an example of a layout widget. It takes a list of children and arranges them vertically. I found this widget jarring at first and assumed it would arrange its children horizontally. Yup, you’ve guessed it, that’s what the Row widget does!

Notice how the Text widgets are initialised with the userName and userRole variables. Think of it in terms of a binding between the Text widget and the instance variable. So when the variable changes the Text automatically updates….right?

Updating State

It’s not as straightforward as updating the variable. You need to pass the function to change the state variables to the setState() function. In order words, the argument to the setState function is itself a function. This ensures the framework is notified that the internal state of this object has changed, which causes the build() method to be rerun.

If you’ve worked with a XAML based framework like WPF or Xamarin, then this is similar to binding a view model property to control property and using INotifyPropertyChanged to broadcast changes.

setState(() {
_userName = "Homer";
_userRole = "Sector 7G";
});

Summary

That concludes this introduction to Flutter. I hope this post will help you to create and run simple Flutter applications on Android and know the difference between Stateless and Stateful widgets.

--

--