How to create a Flutter app
There are two main ways to create a Flutter app: either via the command line or in your preferred IDE. We’re going to start by using the command line to get a clear understanding of what is going on when you create a new app.
For later apps, it’s perfectly fine to use your IDE, but just be aware that all it is doing is calling the command line under the hood.
Before you begin, it’s helpful to have an organized place on your computer to save your projects. This could be anywhere you like, as long as it’s consistent. While there are no strict rules for folder names, there are a few conventions you should follow. For directories:
- Use lowercase letters and separate words with underscores: for example,
project_name
. - Avoid spaces and special characters in your folders and file names.
- When choosing a folder for a Flutter project, you should avoid synchronized spaces like Google Drive or OneDrive, as they might decrease performance and create conflicts when working in teams.
As such, before creating your apps, make sure you have created a directory where your projects will be saved.
How to do it...
Flutter provides a tool called flutter create
that will be used to generate projects. There are a whole bunch of flags that we can use to configure the app, but for this recipe, we’re going to stick to the basics.
If you are curious about what’s available for any Flutter command-line tool, in your Terminal simply type flutter <command> --help
. In this case, it would be flutter create --help
. This will print a list of all the available options and examples of how to use them.
In the directory you have chosen to create your Flutter projects, type this command to generate your first project:
flutter create hello_flutter
- This command assumes you have an internet connection since it will automatically reach out to the official repositories to download the project’s dependencies.
- If you don’t currently have an internet connection, type the following instead:
flutter create --offline hello_flutter
You will eventually need an internet connection to synchronize your packages, so it is recommended to check your network connection before creating a new Flutter project.
Now that a project has been created, let’s run it and take a look. You have several options for your target:
- Connecting a device to your computer
- Starting an emulator/simulator
- Running the app on a Chrome or Edge web browser
- Running the app on your desktop
- Type this command to see the devices currently available on your computer:
flutter devices
- To specifically see the emulators you have installed on your system, type:
flutter emulators
- You should see a list of the available emulators/simulators. Now, to boot an emulator on your system:
- On Windows/Linux, type the command:
flutter emulators --launch [your device name, like: Nexus_5X_API_30] cd hello_flutter flutter run
- On a Mac, type the command:
flutter emulators --launch apple_ios_simulator cd hello_flutter flutter run
- On Windows/Linux, type the command:
- To run your app on one of the available devices, type the following command:
flutter run -d [your_device_name]
- After your app has finished building, you should see a demo Flutter project running in your emulator:
Figure 2.1: Flutter’s default “Hello World” app in an iOS Simulator
- Go ahead and play around with it. The circular button at the bottom right of the screen is called a Floating Action Button, and it’s a widget (much, much more about that in the remainder of this book, starting from Chapter 4, Introduction to Widgets!).
- When you are done, type
q
in the terminal to close your app.
How to choose a platform language for your app
Both iOS and Android are currently in the middle of a revolution of sorts. When both platforms started over 10 years ago, they used the Objective-C programming language for iOS, and Java for Android. These are great languages, but sometimes can be a little long and complex to work with.
To solve this, Apple has introduced Swift for iOS, and Google has adopted Kotlin for Android.
These languages are currently automatically selected for new apps.
If you want to use the older languages (for compatibility reasons) when creating an app, enter this command into your Terminal:
flutter create \
--ios-language objc \
--android-language java \
hello_older_languages
In this way, Objective-C and Java will be chosen. You are also never locked into this decision; if later down the road you want to add some Kotlin or Swift code, there is nothing stopping you from doing so.
It’s important to keep in mind that the majority of your time will be spent writing Dart code. Whether you choose Objective-C or Kotlin, this won’t change much.
Where do you place your code?
The files that Flutter generates when you build a project should look something like this:
Figure 2.2: A Flutter project structure
The main folders in your projects are listed here:
android
build
ios
lib
linux
macos
test
web
windows
The android
, ios
, linux
, web
, and windows
folders contain the platform shell projects that host our Flutter code. You can open the Runner.xcworkspace
file in Xcode or the android
folder in Android Studio, and they should run just like normal native apps. Any platform-specific code or configurations will be placed in these folders. While Flutter uses a single code base for all platforms, when you build your app, it generates the specific code for each platform using these folders.
To increase performance when you build your app, Dart and Flutter support both Just-In-Time (JIT) and Ahead-Of-Time (AOT) compilation.
JIT compiling takes the source code of an app and translates it into machine code during execution. This means faster development, as the code can be tested while updating, and your code can be recompiled while the app is running.
With AOT compilation, the code is compiled before the program execution. This builds a machine code executable that can then be run on your target machine. This means better performance for your apps.
Simplifying things a little, Flutter uses JIT for debug builds and AOT for release builds, taking the best of the two worlds.
The build
directory contains all the artifacts that are generated when you compile your app. The contents of this folder should be treated as temporary files since they change every time you run a build. You should also add this folder to your gitignore
file so that it won’t bloat your repository.
The gitignore
file contains a list of files and folders that Git should ignore when tracking changes in a project. As soon as you initialize a project with Git, this file will be added to your project’s root directory.
The lib
folder is the heart and soul of your Flutter app. This is where you put all your Dart code. When a project is created for the first time, there is only one file in this directory: main.dart
. Since this is the main folder for the project, you should keep it organized. We’ll be creating plenty of subfolders and recommending a few different architectural styles throughout this book.
The next file, pubspec.yaml
, holds the configuration for your app. This configuration file uses a markup language called YAML Ain’t Markup Language (YAML), which you can read more about at https://yaml.org. In the pubspec.yaml
file, you’ll declare your app’s name, version number, dependencies, and assets. pubspec.lock
is a file that gets generated based on the contents of your pubspec.yaml
file. It can be added to your Git repository, but it shouldn’t be edited manually.
Finally, the last folder is test
. Here, you can put your unit and widget tests, which are also just Dart code. As your app expands, automated testing will become an increasingly important technique to ensure the stability of your project. You will create a test in the Creating a unit test recipe later in this chapter.
Hot reload—refresh your app without recompiling
Probably one of the most important features in Flutter is stateful hot reload. Flutter has the ability to inject new code into your app while it’s running, without losing your position (state) in the app. The time it takes to update code and see the results in an app programmed in a platform language could take up to several minutes. In Flutter, this edit/update cycle is down to seconds. This feature alone gives Flutter developers a competitive edge.
There is a configuration that allows executing a hot reload every time you save your code, causing the whole feature to become almost invisible.
In Android Studio/IntelliJ IDEA, open the Preferences window and type hot
into the search field. This should quickly jump you to the correct setting:
Figure 2.3: Android Studio Flutter hot reload configuration
Verify that the Perform hot reload on save setting is checked. While you are there, double-check that Format code on save is also checked.
In VS Code, open your Settings from File > Preferences > Settings. Type flutter hot reload
in the search field. Here you can specify the Flutter Hot Reload On Save option with one of the available values:
- never: No hot reload executed when saving
- all: Hot reload triggered for both manual save and autosave
- allDirty: Hot reload triggered for both manual save and autosave only if the saved file had changes
- manual: Hot reload for manual save only
- manualDirty: Hot reload for manual save only if the saved file had changes
I would choose the all option if performance on your machine does not degrade, as it frees you from having to save manually when you make changes.
Let’s see this in action:
- In Android Studio or IntelliJ IDEA, open the Flutter project you created earlier by selecting File > Open. Then, select the
hello_flutter
folder. - After the project loads, you should see a toolbar in the top-right corner of the screen with a green play button. Press that button to run your project:
Figure 2.4: Android Studio toolbox
- When the build finishes, you should see the app running in the emulator/simulator. For the best effect, adjust the windows on your computer so you can see both, side by side:
Figure 2.5: The Flutter default project on an Android emulator
- In the
main.dart
file in thelib
folder, update the primary swatch togreen
, as shown in the following code snippet, and hit Save:class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.green, ), home: MyHomePage(title: 'Flutter Demo Home Page'), ); } }
- When you save the file, Flutter will repaint the screen:
Figure 2.6: The default app after a color change
In VS Code, the pattern is very similar:
- Click on the triangle on the left of the screen, then on the Run and Debug button:
Figure 2.7: Visual Studio Code Run and Debug menu
- Update the primary swatch to
green
, as shown in the following code snippet, and hit the Save button:class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.green, ), home: MyHomePage(title: 'Flutter Demo Home Page'), ); } }
- Only if your app does not update, click on the Hot reload button (denoted by a lightning bolt) from the debug toolbar or press F5. This will update the color of your app to green:
Figure 2.8: Visual Studio Code debug toolbar
It may seem simple now, but this small feature will save you hours of development time in the future!