Everything Flutter (Part 3) : Write Your First Flutter App (Part 1)
Flutter is Google's mobile SDK for crafting high-quality native interfaces on iOS and Android in record time. Flutter works with existing code, is used by developers and organizations around the world, and is free and open source. In this codelab, you'll create a simple Flutter app. If you are familiar with object-oriented code and basic programming concepts such as variables, loops, and conditionals, you can complete this codelab. You don't need previous experience with Dart or mobile programming.
What you'll learn in part 1
- How to write a Flutter app that looks natural on both iOS and Android.
- Basic structure of a Flutter app.
- Finding and using packages to extend functionality.
- Using hot reload for a quicker development cycle.
- How to implement a stateful widget.
- How to create an infinite, lazily loaded list.
In part 2 of this codelab, you'll add interactivity, modify the app's theme, and add the ability to navigate to a new page (called a route in Flutter).
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 ten names at a time. As the user scrolls, new batches of names are generated. The user can scroll forever, with new names being continually generated.
The animated GIF shows how the app works at the completion of part 1:
Set up your Flutter environment
You need two pieces of software to complete this lab: the Flutter SDK, and an editor. This codelab assumes Android Studio, but you can use your preferred editor.
You can run this codelab using any of the following devices:
- A physical device (Android or iOS) connected to your computer and set to developer mode.
- The iOS simulator. (Requires installing XCode tools.)
- The Android emulator. (Requires setup in Android Studio.)
Create the initial 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). You'll be modifying this starter app to create the finished app.
Tip: If you don't see "New Flutter Project" as an option in your IDE, make sure you have the plugins installed for Flutter and Dart.
In these codelabs, 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.
Tip: When pasting code into your app, indentation can become skewed. You can fix this automatically with the Flutter tools:
- Android Studio / IntelliJ IDEA: Right-click the dart code and select Reformat Code with dartfmt.
- VS Code: Right-click and select Format Document.
- Terminal: Run flutter format <filename>.
Run the app. You should see either Android or iOS output, depending on your device.
Tip: The first time you run on a physical device, it can take awhile to load. After this, you can use hot reload for quick updates. Save also performs a hot reload if the app is running.
- 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 fat arrow (=>) notation, Use fat arrow notation for one-line functions or methods.
- The app extends StatelessWidget, which makes the app itself a widget. In Flutter, almost everything is a widget, including alignment, padding, and layout.
- The Scaffold widget, from the Material library, provides a default app bar, a 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 Center widget containing a Text child widget. The Center widget aligns its widget subtree to the center of the screen.
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 pub.dartlang.org.
The pubspec file manages the assets for a Flutter app. In pubspec.yaml, append english_words: ^3.1.0(english_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:
In lib/main.dart, import the new package:
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).
Next, you'll use the english_words package to generate the text instead of using the string "Hello World".
Make the changes shown below:
Tip: "Pascal case" (also known as "upper camel case"), means that each word in the string, including the first one, begins with an uppercase letter. So, "upper camel case" becomes "UpperCamelCase".
If you didn't change Center to "new Center", the type system will warn that the Center object should not be typed as a constant (const), because its child Text object is no longer a constant. Therefore, both Center and Text must create instances using new.
If the app is running, use the hot reload button () 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.
If your app is not running correctly, look for typos. If needed, use the code at the following links to get back on track.
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. It can go anywhere in the file outside of MyApp, but the solution places it at the bottom of the file. Add the following text:
Notice the declaration State<RandomWords>. This indicates that we're using the generic State class specialized for use with RandomWords. Most of the app's logic and state resides here—it maintains the state for the RandomWords widget. 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.
RandomWordsState depends on the RandomWords class. You'll add that next.
Add the stateful RandomWords widget to main.dart. The RandomWords widget does little else besides creating its State class:
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 from MyApp to RandomWordsState.
Add the build method to RandomWordsState, as shown below:
Remove the word generation code from MyApp by making the changes below:
Hot reload the app. The app should behave as before, displaying a word pairing each time you hot reload or save the app.
Tip: If you see the following warning on a hot reload, consider restarting the app:
Not all changed program elements ran during view reassembly; consider restarting.
It may be a false positive, but restarting ensures that your changes are reflected in the app's UI.
If your app is not running correctly, you can use the code at the following link to get back on track.
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 _suggestions list to the RandomWordsState class for saving suggested word pairings. Also, add a _biggerFont variable for making the font size larger.
Tip: Prefixing an identifier with an underscore enforces privacy in the Dart language.
Next, you'll add a _buildSuggestions() function to the RandomWordsState class. This method will build the ListView that displays the suggested word pairing.
The ListView class 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—the BuildContext, and the row iterator, i. The iterator begins at 0 and increments each time the function is called—once for every suggested word pairing. This model allows the suggestion list to grow infinitely as the user scrolls.
Add the entire _buildSuggestions function, shown below, to the RandomWordsState class (delete the comments, if you prefer):
The _buildSuggestions function calls _buildRow once per word pair. This function displays each new pair in a ListTile, which will allow you to make the rows more attractive in part 2.
Add a _buildRow function to RandomWordsState:
Update the build method for RandomWordsState to use _buildSuggestions(), rather than directly calling the word generation library. (Scaffold implements the basic Material Design visual layout.)
Update the build method for MyApp, changing the title, and changing the home to be a RandomWords widget.
Restart the app. You should see a list of word pairings, no matter how far you scroll.
If your app is not running correctly, you can use the code at the following link to get back on track.
You have completed part 1 of this codelab!
Other next steps
Learn more about the Flutter SDK:
Other resources include: