by Stanislav Termosa
An Introduction to Flutter: The Basics
I’ve been hearing about how amazing Flutter is and I’ve decided to try it out to learn something new. I wished to have more topics to discuss with colleagues.
It started by watching, then reading, and then I started coding. It was a good experience. Apps were running, and everything that was written wasn’t hard to understand.
However, the process wasn’t smooth enough - some of the details were not explained in that resources. Also, since everything was new to me (the platform itself, programming language, approaches and even mobile app development), the lack of those details was painful.
Any time something didn’t work, I didn’t know what to Google: Dart, Flutter, Window, Screen, Route, Widget?
I decided that reading the documentation on Dart, Flutter and all of its widgets wouldn’t be a good idea as it would be too time consuming. Also, I didn’t have a lot of time as the purpose was to get to know the new thing, and not to become an expert in the field. I thought at that moment that it would be amazing if there was a short guide on Flutter, that would describe all the necessary concepts to understand the framework and be able to write simple apps, but no more!
About The Guide
Most of the articles on this topic are well written and straightforward. The problem is that they require you to know some basic things, and those small things are not described in articles that are suppose to give you basic knowledge.
In this series, I’ll try to avoid that problem. We’ll start from scratch and create applications sorting out every step we do. During this series, we will use all basic widgets, design a unique interface, interact with native modules, and build our app for both iOS and Android platforms.
This series is written from the perspective of a web developer. Most of you are probably familiar with this stack. The analogy with a familiar platform is better than one where you have to build houses or use Animal, Dog, Foo, Bar, etc.
I’ll keep it short, to save your time. For the most curious of you, I’ll put useful links around the text.
About The Platform
Flutter is very new, but a promising platform, that has attracted the attention of large companies who’ve released their apps already. It is interesting because of its simplicity compared to developing web applications, and because of its speed as compared with native applications.
High performance and productivity in Flutter are achieved by using several techniques:
- Flutter doesn’t use native UI components. That may sound awkward at first. However, because components are implemented in Flutter itself, there is no communication layer between the view and your code. Due to this, games hit the best speed for their graphics out of the smartphones. So buttons, text, media elements, background are all drawn by Flutter’s graphics engine. As an aside, it should be mentioned that the bundle of the Flutter “Hello, World” application is quite small: iOS ≈ 2.5Mb and Android ≈ 4Mb.
- Flutter uses a declarative approach, inspired by the React web framework, to build its UI based on widgets (named “components” in the world of the web). To get more out of widgets, they are rendered only when necessary, usually when their state has been changed (just like the Virtual DOM does for us).
- In addition to all of the above, the framework has integrated Hot-reload, so typical for the web, but still missing on native platforms. This allows the Flutter framework to automatically rebuild the widget tree, allowing you to quickly view the effects of your changes.
There is an excellent article on the practical use of these features from an Android developer who recreated his application from Java to Dart and shared his impressions.
I wanted to share with you some numbers from his article.
- Java (before): Number of files = 179 and Lines of code 12,176
- Dart (after): Number of files = 31 and Lines of code 1,735.
I tried to write an article on Dart for you, to describe the minimal scope that is required for Flutter. After several attempts, I was still failing to write it so that it was short and covered the core concepts at the same time. Authors of A Tour of the Dart Language coped well with this task!
This topic, just like a Dart, is well covered in the official guide — so I won’t copy it here.
Go through this short setup guide, by choosing your OS and following it step-by-step. Also, configure your preferred editor to work with Dart and Flutter (usually it requires 2 different plugins). Run your application to make sure that you are ready to continue.
Here is a tip for MacOS users. If you don’t like how much space is wasted by virtual device bezels, you can turn them off, and switch to an iPhone 8 model (it is not as long as iPhone X):
- Hardware → Device → iOS # → iPhone 8
- Window → Show Device Bezels
It is possible to live without virtual buttons as we have hot keys: Shift + Cmd (⌘) + H - go home, Cmd (⌘) + Right - rotate the phone, and you can find more in the Hardware menu. I would also recommend to turn on the on-screen keyboard, as it is important to understand if your application is usable when half of the screen is overlapped. To do so you press Cmd (⌘) + K after you focus on an input field.
Let’s first see what’s in the project generated by the Flutter framework:
- lib/ - just as pub (Dart’s package manager), all the code will be here
- pubspec.yml - stores a list of packages that are required to run the application, just like package.json does it. You should remember that in Flutter projects you cannot use pub directly, but instead, you will use the Flutter command:
flutter pub get <package_name>
- test/ - I’m sure you know what this is about. Right? You can run them via flutter test
- ios/ & android/ - the code specific for each platform, including app icons and settings where you set what permissions you’ll need for your application (like access to location, Bluetooth).
We don’t need to know more about the files in the folder for now. Let’s open the lib/ folder where main.dart is waiting for us. As you can guess this one is the entry point of our application. Just like in the C language (or tons of others) the app will be executed by calling the main() function.
About widgets (Hello World is here)
In Flutter everything is built on Widgets. UI elements, styles, themes, and even state is managed in specific Widgets. Let’s start from a small application.
Replace the code from main.dart with the one given below, read the comments, and run the application.
runApp(…) only has a widget argument. The widget will become the root widget for the whole application. BTW, changing the root widget cannot be handled by Hot-reload so you’ll have to restart your application to see changes.
Text(…) - Flutter cannot render text without knowing what’s the preference for text direction. To render text, we have to set Text.textDirection. Don’t confuse it with the CSS text-align rule. It is the analogy of direction - the part of the internationalization API. However, don’t worry, we won’t need to set it for each Text widget - later we’ll see how to set it for the whole app.
Is your application running already? Yay! “Hello, World!” is on the screen now. Right? Eh, something went wrong.
The text is overlapped by the notch. We can use the whole screen for our application, and we have printed our content at the very top of it where system information is also rendered.
Let’s try to shift our content.
Center(…) is the widget that aligns another widget given in child property in the center of itself. You’ll often see child and children properties in Flutter applications, because almost all widgets are using them if they need one or several widgets to be rendered inside of them.
A composition of widgets in Flutter is used to represent an interface, to change its look, and to share data. For example, Directionality(…) sets the direction for the text for all nested widgets (so we don’t need to specify it for Text every time).
Let’s take a look at one very important widget, and change the design of our application:
There are several options on how to use the Color(…) widget. We have used the widget with the number given to it using hexadecimal notation. This looks almost the same as we set HEX-colors on the web, but here we have 2 additional symbols at the beginning. This is a number that represents the transparency where 0x00 is fully transparent, and 0xFF is not transparent at all.
TextStyle(…) is more interesting. You can use it to set a color, font size and weight, line spacing, underline text, etc.
The Flutter application is complete! You can read how to build it for Android and iOS, where you can also learn how to publish it to the relevant app store. If it’s not enough for you, I’ve covered a few more topics below.
About Stateless Widgets
Now we know how easy it is to use widgets. The next logical step would be to create our widgets. I’ve mentioned before that there are two kinds of widgets (actually more, but let’s not over complicate it for now). There are stateless and stateful widgets.
We’ve been using stateless widgets in the previous examples. “Stateless” doesn’t mean they don’t have a state at all. Widgets are Dart classes, that can be declared with properties. But changing those properties in a stateless widget won’t affect what has already been rendered. Updating properties of a stateful widget will trigger life cycle hooks and render its content using the new state. We’ll start with Stateless widgets as they seem to be a bit easier.
To create one, we need:
- A beautiful name for the new class.
- To extend our class from StatelessWidget.
- Implement the build() method, that will receive one argument of type BuildContext and return a result of type Widget.
An example of the widget with an argument:
I have nothing more to add about Stateless widgets. They are simple.
About Hot Reload
Notice that once we have moved our application content to the separate widget, the application is re-rendered each time we save our changes. This is hot-reload in action.
It is also crucial to understand, that while you are working in development mode with hot-reload enabled, the application will work much slower than in release mode.
We will create a StatefulWidget in the next section. To make sure it will be interesting we need to be able to change the state of the widget, right? We’ll use GestureDetector(…) for this purpose. This widget will not render anything to the screen but handles user interaction with the screen and calls related functions given to it.
The example below creates a blue button in the center of the screen, and once this button is pressed, the text is printed to the terminal:
Press the button, and the message will be printed to the terminal. Press it again, and the text will appear again.
About Stateful Widgets
StatefulWidget’s are simple. Yeah, even simpler than StatelessWidget’s! However, there is a nuance. They do not exist by themselves. They require an extra class to store the state of the widget. Moreover, the visual part of the widget becomes its state.
Here is the example of the StatefulWidget class:
We’ve created an “empty” widget that implements only one method and doesn’t contain state or UI representation. Forcing such separation, Flutter seeks greater optimization of the application.
The state object is also not complicated. Indeed, it is just like our StatelessWidget. The main difference is its parent class.
We’ve built such a wonderful application. Great result!
Before we end this part, let’s take a look at a few more interesting widgets. This time we’ll write more code at once, and I won’t explain every line. You can probably already understand most of the code:
In the next article, we will look at them more precisely. We will also learn how to assemble several widgets and create a sexy app using Flutter’s Material library.
If you wish to learn more about mentioned topics here is the list of interesting links:
- Coding using VS Code and IntelliJ
- More details on widgets
- It is also important to read about Hot reload to understand when and why your application may not be updated automatically.