4. Do Coding
Write your first Flutter app, part 1

This is a guide to creating your first Flutter app. If you are familiar with object-oriented code and basic programming concepts such as variables, loops, and conditionals, you can complete this tutorial. You don’t need previous experience with Dart or mobile programming.
This guide is part 1 of a two-part codelab. You can find part 2 on Google Developers. Part 1 can also be found on Google Developers.
What you’ll build in part 1
You’ll implement a simple mobile app that generates proposed names for a startup company. The user can select and unselect names, saving the best ones. The code lazily generates names. As the user scrolls, more names are generated. There is no limit to how far a user can scroll.
The animated GIF shows how the app works at the completion of part 1.
Step 1: Create the starter Flutter app
Create a simple, templated Flutter app, using the instructions in Getting Started with your first Flutter app. Name the project startup_namer (instead of myapp).
In this codelab, you’ll mostly be editing lib/main.dart, where the Dart code lives.
- Replace the contents of
lib/main.dart.
Delete all of the code from lib/main.dart. Replace with the following code, which displays “Hello World” in the center of the screen.lib/main.dart// Copyright 2018 The Flutter team. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. 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'), ), ), ); } }
- Run the app in the way your IDE describes. You should see either Android or iOS output, depending on your device.

Android 
iOS
Observations
- This example creates a Material app. Material is a visual design language that is standard on mobile and the web. Flutter offers a rich set of Material widgets.
- The
main()method uses arrow (=>) notation. Use arrow notation for one-line functions or methods. - The app extends
StatelessWidgetwhich makes the app itself a widget. In Flutter, almost everything is a widget, including alignment, padding, and layout. - The
Scaffoldwidget, from the Material library, provides a default app bar, title, and a body property that holds the widget tree for the home screen. The widget subtree can be quite complex. - A widget’s main job is to provide a
build()method that describes how to display the widget in terms of other, lower level widgets. - The body for this example consists of a
Centerwidget containing aTextchild widget. The Center widget aligns its widget subtree to the center of the screen.
Step 2: Use an external package
In this step, you’ll start using an open-source package named english_words, which contains a few thousand of the most used English words plus some utility functions.
You can find the
english_words package, as well as many other open source packages, on the Pub site.- The pubspec file manages the assets and dependencies for a Flutter app. In
pubspec.yaml, addenglish_words(3.1.0 or higher) to the dependencies list: - While viewing the pubspec in Android Studio’s editor view, click Packages get. This pulls the package into your project. You should see the following in the console:
$ flutter pub get Running "flutter pub get" in startup_namer... Process finished with exit code 0PerformingPackages getalso auto-generates thepubspec.lockfile with a list of all packages pulled into the project and their version numbers. - In
lib/main.dart, import the new package:lib/main.dartimport 'package:flutter/material.dart'; import 'package:english_words/english_words.dart';
As you type, Android Studio gives you suggestions for libraries to import. It then renders the import string in gray, letting you know that the imported library is unused (so far). - Use the English words package to generate the text instead of using the string “Hello World”:
- If the app is running, hot reload to update the running app. Each time you click hot reload, or save the project, you should see a different word pair, chosen at random, in the running app. This is because the word pairing is generated inside the build method, which is run each time the MaterialApp requires rendering, or when toggling the Platform in Flutter Inspector.

Android 
iOS
Problems?
If your app is not running correctly, look for typos. If you want to try some of Flutter’s debugging tools, check out the DevTools suite of debugging and profiling tools. If needed, use the code at the following links to get back on track.
Step 3: Add a Stateful widget
Stateless widgets are immutable, meaning that their properties can’t change—all values are final.
Stateful widgets maintain state that might change during the lifetime of the widget. Implementing a stateful widget requires at least two classes: 1) a StatefulWidget class that creates an instance of 2) a State class. The StatefulWidget class is, itself, immutable, but the State class persists over the lifetime of the widget.
In this step, you’ll add a stateful widget,
RandomWords, which creates its State class, RandomWordsState. You’ll then use RandomWords as a child inside the existing MyApp stateless widget.- Create a minimal state class. Add the following to the bottom of
main.dart:lib/main.dart (RandomWordsState)class RandomWordsState extends State<RandomWords> { // TODO Add build() method }
Notice the declarationState<RandomWords>. This indicates that we’re using the generic State class specialized for use withRandomWords. Most of the app’s logic and state resides here—it maintains the state for theRandomWordswidget. This class saves the generated word pairs, which grows infinitely as the user scrolls, and favorite word pairs (in part 2), as the user adds or removes them from the list by toggling the heart icon.RandomWordsStatedepends on theRandomWordsclass. You’ll add that next. - Add the stateful
RandomWordswidget tomain.dart. TheRandomWordswidget does little else beside creating its State class:lib/main.dart (RandomWords)class RandomWords extends StatefulWidget { @override RandomWordsState createState() => RandomWordsState(); }
After adding the state class, the IDE complains that the class is missing a build method. Next, you’ll add a basic build method that generates the word pairs by moving the word generation code fromMyApptoRandomWordsState. - Add the
build()method toRandomWordsState:lib/main.dart (RandomWordsState)class RandomWordsState extends State<RandomWords> { @override Widget build(BuildContext context) { final wordPair = WordPair.random(); return Text(wordPair.asPascalCase); } }
- Remove the word generation code from
MyAppby making the changes shown in the following diff: - Restart the app. The app should behave as before, displaying a word pairing each time you hot reload or save the app.
Problems?
If your app is not running correctly, look for typos. If you want to try some of Flutter’s debugging tools, check out the DevTools suite of debugging and profiling tools. If needed, use the code at the following link to get back on track.
Step 4: Create an infinite scrolling ListView
In this step, you’ll expand
RandomWordsState to generate and display a list of word pairings. As the user scrolls, the list displayed in a ListView widget, grows infinitely. ListView’s builder factory constructor allows you to build a list view lazily, on demand.- Add a
_suggestionslist to theRandomWordsStateclass for saving suggested word pairings. Also, add a_biggerFontvariable for making the font size larger.lib/main.dartclass RandomWordsState extends State<RandomWords> { final _suggestions = <WordPair>[]; final _biggerFont = const TextStyle(fontSize: 18.0); // ··· }
Next, you’ll add a_buildSuggestions()function to theRandomWordsStateclass. This method builds theListViewthat displays the suggested word pairing.TheListViewclass provides a builder property,itemBuilder, that’s a factory builder and callback function specified as an anonymous function. Two parameters are passed to the function—theBuildContext, and the row iterator,i. The iterator begins at 0 and increments each time the function is called. It increments twice for every suggested word pairing: once for the ListTile, and once for the Divider. This model allows the suggested list to grow infinitely as the user scrolls. - Add a
_buildSuggestions()function to theRandomWordsStateclass:lib/main.dart (_buildSuggestions)Widget _buildSuggestions() { return ListView.builder( padding: const EdgeInsets.all(16.0), itemBuilder: /*1*/ (context, i) { if (i.isOdd) return Divider(); /*2*/ final index = i ~/ 2; /*3*/ if (index >= _suggestions.length) { _suggestions.addAll(generateWordPairs().take(10)); /*4*/ } return _buildRow(_suggestions[index]); }); }
- The
itemBuildercallback is called once per suggested word pairing, and places each suggestion into aListTilerow. For even rows, the function adds aListTilerow for the word pairing. For odd rows, the function adds aDividerwidget to visually separate the entries. Note that the divider might be difficult to see on smaller devices. - Add a one-pixel-high divider widget before each row in the
ListView. - The expression
i ~/ 2dividesiby 2 and returns an integer result. For example: 1, 2, 3, 4, 5 becomes 0, 1, 1, 2, 2. This calculates the actual number of word pairings in theListView, minus the divider widgets. - If you’ve reached the end of the available word pairings, then generate 10 more and add them to the suggestions list.
The_buildSuggestions()function calls_buildRow()once per word pair. This function displays each new pair in aListTile, which allows you to make the rows more attractive in the next step. - The
- Add a
_buildRow()function toRandomWordsState:lib/main.dart (_buildRow)Widget _buildRow(WordPair pair) { return ListTile( title: Text( pair.asPascalCase, style: _biggerFont, ), ); }
- In the
RandomWordsStateclass, update thebuild()method to use_buildSuggestions(), rather than directly calling the word generation library. (Scaffold implements the basic Material Design visual layout.) Replace the method body with the highlighted code:lib/main.dart (build)@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Startup Name Generator'), ), body: _buildSuggestions(), ); }
- In the
MyAppclass, update thebuild()method by changing the title, and changing the home to be aRandomWordswidget: - Restart the app. You should see a list of word pairings no matter how far you scroll.

Android 
iOS
Problems?
If your app is not running correctly, look for typos. If you want to try some of Flutter’s debugging tools, check out the DevTools suite of debugging and profiling tools. If needed, use the code at the following link to get back on track.
Profile or release runs
So far you’ve been running your app in debug mode. Debug mode trades performance for useful developer features such as hot reload and step debugging. It’s not unexpected to see slow performance and janky animations in debug mode. Once you are ready to analyze performance or release your app, you’ll want to use Flutter’s “profile” or “release” build modes. For more details, see Flutter’s build modes.
Comments