Sydney Flutter Jam #1

Brett Morgan
7 min readOct 8, 2018

--

I recently live coded a Flutter app live on stage, without any preparation. It was an amusing experience of reading documentation, exploring potential approaches, all while my audience were also exploring live in their own code editors.

The intent of the night was to run through Udacity’s Build Native Mobile Apps with Flutter, but the 30 developers in the room wanted to take control of their adventure. They wanted an app that listed the locations of the Google offices around the world. The audience is always right, so that’s what we built together.

Step 1, first pixels on screen

Starting with flutter create, we started in on creating a Flutter app using the Material Component widgets. If you have yet to install Flutter, please see the Flutter Getting Started documentation. I’ve used Android Studio, IntelliJ IDEA and Visual Studio Code for developing Flutter applications, and all three work quite nicely. There is documentation for setting up editors for Flutter.

Creating a flutter app can be done either from the command line, or using an editor workflow. Here is what the command line app creation step looks like:

If you would prefer to have your editor build out the boilerplate project code, please see our docs for Android Studio and Visual Studio Code.

You can run this sample app as is, but I find most people first coming to Flutter find this initial sample a but intimidating. It is demonstrating a lot of concepts that are more advanced than Hello World. So, let’s simplify it down, and build something a lot easier to grapple with.

We can ignore most of the sixty odd files that flutter create wrote out. The one file we are going to spend a fair amount of time with is lib/main.dart. This file contains the main entry point for our application.

Breaking up this code visually, the first of the two one liners includes the Material Components widgets. The second one liner is our main entry point function, defined using the short-hand “fat arrow” single expression function syntax. For function bodies that consist of more than a single expression, Dart also has the conventional block syntax as well.

Following this we have two class definitions. The first class, MyApp, is a stateless widget that is responsible for bringing up our application. It does this by constructing and configuring a MaterialApp widget, passing in a title, a theme, and our content in the form of MyHomePage. MaterialApp is responsible for navigating between the different pages of our application, or as they are known in Flutter land, routes. Our app consists of a single route — called MyHomePage.

The last visual block in this listing is our MyHomePage stateless widget, which is responsible for painting all of the pixel visible on the screen. MyHomePage achieves this end by returning a Scaffold widget containing an AppBar widget and a Center’ed Text widget from the build method. In Flutter, pretty much everything is a widget, both the visual components, e.g. Text and AppBar, as well as the layout components, in this case Center and Scaffold.

This application, as it currently stands, really doesn’t do anything more than just show some text centered on the screen. The really nice thing about Flutter is that if the code doesn’t really make sense, you can alt-click your way into the Flutter code base, following a series of classes almost all the way down. It’s a fully open sourced stack, and the vast majority of the code is in easily digestible Dart.

The one piece of potentially confusing Dart syntax in this code is the shorthand around the MyHomePage constructor. The first member declared in MyHomePage is the string member title, declared final. So, it has to be filled in by the MyHomePage constructor, yet the constructor has no body. What gives?

The one line constructor is actually saying a couple of different things with a very economic syntax. The first is, by wrapping the constructor arguments with {} we are marking the arguments as optional named arguments. Flutter uses named arguments in a lot of it’s APIs to make the code more declarative. Second, by specifying the argument as this.name, we are informing dart that the argument is setting the value of the member. No more need for this.name = name; in the constructor body. Magic!

For fun things to play with in this code, I suggest you change the text and theme colors. These should both hot reload, which may or may not be tied to file save, depending on your editor’s Flutter tooling integration. If you are running flutter run on the command line, you’ll have to hit r to signal flutter to reload. The other thing to play with is Dart’s formatting. You can choose whether to layout the widgets in more traditional programming language function call style, or more like HTML markup style, depending on whether you have trailing commas. This gives you control over your code presentation, even with automatic code formatting.

You can see all the code for this step on GitHub.

Step 2, listing office locations

We want to build out a list of office locations, so we should look for the Material widgets that help us accomplish this goal. In the Layout widgets catalog, we find a likely candidate in the for of the ListView class. In the Material Components widgets catalog, we find another useful class, in the form of the ListTile class, which should look familiar to anyone who has used a Material app like GMail.

In this step, we create a Stateless widget for displaying each office location, built by configuring up a ListTile appropriately. We construct a short list of offices programmatically, leaving off loading the content dynamically until Step 3.

In this code listing I have elided the material import line, the main entry point, and the definition of the MyApp class. These have all stayed the same from the first step. The changes that have happened in this step are the creation of a Location widget to display each of the office locations, and the additional logic added to MyHomePage.

The common code patterns that come up often in developing Flutter apps are documented in the Flutter Cookbook. The pattern we are using here is called the Basic List, covering how to easily display a short list of content widgets.

You can see all the code for this step on GitHub.

Step 3, loading locations from the network

Now that we have a list of locations displaying, it is time to load content from a JSON API endpoint. In this step we will take the visual infrastructure that we have built up in the previous steps and attach it directly to a web end point using Dart’s built in JSON parser and pub packaged HTTP client.

Working through this file, we have a series of changes. At the top of the file we have added a bunch of new imports:

  • dart:async enables declaration and usage of asynchronous functions,
  • dart:convert enables Dart’s native JSON parsing capability, and
  • package:http/http.dart enables easy HTTP requests.

This package dependency requires adding a dependency to our pubspec.yaml file. To see the instructions on how to do this, please see the HTTP Pub package page.

I have made a change all the way through the app infrastructure to thread a http.Client through the app, to enable easy mock testing of the API request. I have made a minimal smoke test that feeds fake data to the app through a mocked out HTTP client, and then makes sure it is on screen. See the code in test/widget_test.dart.

It is worth noting that there are alternate approaches to passing context specific objects through the potentially deep hierarchy of widgets in a Flutter app, e.g. the InheritedWidget, that I’m not going to use in this sample.

The first major change in the hierarchy of Widgets that we are using in this app is in the base MyApp widget, which has changed from a Stateless Widget to a Stateful Widget. We have made this change to enable capturing the state change that happens when we get content back from the API endpoint. To get a really good handle on the difference between Stateless and Stateful Widgets in Flutter, please see the Adding Interactivity to Your Flutter App tutorial.

An equally valid way of handling this change is to use a FutureBuilder. The Flutter team have put together a YouTube video that gives a high level overview of the capabilities of this Widget. A fun exercise for the reader is to convert this app to use FutureBuilder to render the list of locations.

We have also added a factory constructor to the Location class to enable this class to construct instances from JSON data. This approach is summarised in the Flutter JSON documentation as the manual approach to handling JSON data, and appropriate for smaller JSON structures. For more intricate data structures there are good alternatives such as json_serializable and built_value.

You can see all the code for this step on GitHub.

Step 4, investigating Cupertino widgets

Step 4 is an investigation into the Cupertino widgets. I’m not going to describe the code in detail, as I am still changing the code as I figure out better ways of implementing the design.

There are a couple of known issues that need rectifying. The first is that the spinner widget used to show that the location images are loading is still in the widget tree, even after the images load. This is causes needless work for the CPU.

My second issue is with the way I am building the list tiles feels overly complex. We need to build more Cupertino widgets to make this more akin to the Material Component widget experience.

As you probably guessed, you can see all the code for this step on GitHub.

Let me know what you think of what I have built here, and if you can see a better way to approach what I have done here, please feel free to send the project a Pull Request on GitHub. Thanks!

--

--

Brett Morgan

I am a developer relations engineer for Google’s Flutter and Dart programming language.