Author: Karsten Silz
Oct 27, 2021   |  updated Jun 13, 2022 10 min read


Getting Started: Flutter

What’s This?

I help you get started with Google’s Flutter, the most popular cross-platform UI toolkit for building native mobile, desktop, and web applications.

Table Of Contents


Use React Native.

Learning Flutter & Dart

The Flutter website is an excellent place to get familiar with Flutter. Flutter uses the Dart programming language to create natively-compiled applications for mobile, web, desktop & embedded. Both Flutter and Dart can use plugins that have [a great portal]((#plugin-portal).

Learning Dart

You start with the Dart language tour. Java developers take the “Intro to Dart for Java Developers” next. Then you have options:

Installing Flutter

Here are the instructions, straight from the Flutter website:

Learning Declarative UIs

Flutter uses a declarative approach to build UIs. I have a page dedicated to declarative UIs. Please check it out!

Learning Flutter

Here’s a selection of Flutter tutorials and courses:


Widget Sets

Flutter doesn’t use native UI elements (such as text fields or buttons). Instead, it emulates them. Flutter uses the Google open-source Skia Graphics library for that. Chrome and Firefox, Chrome OS, and Android also use Skia. But this also means Flutter only paints pixels: It has to recreate all native iOS/Android UI elements in Flutter. Flutter calls the UI elements “widgets”. Out of the box, Flutter has two widget sets:

  • Material Components: This set is the default set for Flutter. It’s available everywhere Flutter runs.
  • Cupertino: These are iOS-style widgets that are best used when Flutter runs on iPhone or iPad. The set is incomplete: The table view, a heavily used UI element, is missing. A package like flutter_cupertino_settings can fill this void.

By default, we manually have to switch between these two widget sets in our code: Pick a Cupertino widget on iOS/iPadOS and a Material one everywhere else. flutter_platform_widgets does that for us.

There are two open-source widget sets that provide widgets with native look & feel for Windows and macOS: fluent_ui and macos_ui.

Responsive & Adaptive Apps

According to Flutter, a responsive app changes with the screen size and orientation. An adaptive app changes with device type (mobile & desktop) and input type (keyboard & mouse vs. touch).

From what I can tell, the advice for a responsive app is to check the screen width and then update the UI. That seems like a primitive solution compared to other approaches. The web, for instance, has the Bootstrap Grid, CSS Flexbox, and CSS Grid. Android has size classes, as does iOS.

I’ve used flutter_bootstrap for responsive layout on mobile.

Sample Application: Native Look & Feel With Flutter


I built a sample Flutter application with five different, native “Look & Feels” with one codebase: Web, iOS, Android, Windows, and Mac. Here are screenshots from the form screen of that application which demonstrate the differences well.


Web Look & Feel
Web Look & Feel


iOS Look & Feel
iOS Look & Feel


Android Look & Feel
Android Look & Feel


Windows Look & Feel
Windows Look & Feel


macOS Look & Feel
macOS Look & Feel

Getting the Code

The source code for this project is on Github:

You need Flutter to run the application. Please find the installation instructions above. The Flutter installation instructions also tell you which additional tools you need. That’s typically IDEs, such as Android Studio, Visual Studio for Windows, or Apple’s Xcode.

Here’s which platforms you can run. That depends on your development machine operating system:

  • Windows: Android, Web, Windows
  • Linux: Android, Web
  • macOS: Android, Web, iOS, macOS

Source Structure


Use Existing Components (Plugins)

The best code is the one we don’t have to write. That’s why we’d like to use open-source libraries in our apps. In Flutter, they are called plugins. Please see the “Plugins (Libraries)” section below.

Write Your Own Components

Don’t repeat yourself” (DRY) is a valuable software development principle. It generally leads to apps that are easier to maintain. Applying DRY means that we create our own components. There are two prime candidates for that in Flutter:

  • We often style widgets, like buttons or text fields, the same way - fonts, colors, padding, etc. And when we then change, say, the color of a button, we now need to change the color in every place we use it. Instead, we should make that button a component - a widget. Then we don’t have to copy all this code around and have to change the color only in one place.
  • The same applies for our business logic. Let’s say, we load data from and save data to our back-end with HTTP. So we copy the same boilerplate code about HTTP calls and HTTP headers and error handling everywhere. Again, we should make that a component - a class. That class has all the boilerplate code. And all we do is pass in a URL - or a URL and an object to send.

Use Vertical & Horizontal Layers

I suggest structuring an application with horizontal and vertical layers. That makes it easier to manage in the long run. “Manage” means fixing bugs and adding features. But “manage” also means “Where the heck is the code that does X?!”.

Let’s start with vertical layers. We can imagine them as columns in our architecture.

  • Folders for widgets are an easy start in Flutter. Typically, we have one widget per page. So let’s put them into folders. If our app requires sign-in, we have one folder for pages when not signed in, and one folder for the pages when signed in. And our app probably has multiple areas. So we have one folder per area in the “signed-in folder”.
  • Our business logic can have vertical layers, too. Bounded contexts, a concept from Domain-driven design, defines such layers. Let’s say we have an online shop. Then we have areas like the product catalog, inventory management, shipping, and invoicing. They often use the same words but with different meaning: In the product catalog, each product exists only once. In inventory management, a product can exist hundreds or thousands of times, with attributes that the product catalog doesn’t care about (such as a physical location in storage). That’s why we can model product catalog, inventory management, shipping, and invoicing as separate, concealed areas - bounded contexts. Each context has its own set of domain objects and business logic.

We can also have horizontal layers, the rows in our architecture.

  • We should separate our widgets (the presentation logic) from our business logic. So the widgets would instantiate a business logic class and call a load or save method on it.
  • Our business logic itself could contain multiple layers. For instance, our app can have local storage on the device. That would be separate from the layer that calls our back-end.

Redux as Global Data Store

I use Redux as my global data store. When that store changes, my UI refreshes. That helps avoiding UI inconsistencies. And that local state helps my app work when it’s offline.

Redux started in the web world. In Flutter, I persist my state as JSON. I use flutter_redux, redux_persist_flutter, and redux_persist.

Here’s a complete tutorial. Please note, unlike what we see in that tutorial, our code can refresh widgets if just parts of the Redux store change. In the example below, the widget only rebuilds if the current users changes:

Widget build(BuildContext context) {
  return StoreConnector<AppState, UserDetails>(
    converter: (store) => store.state.currentUser,
    distinct: true,
    builder: (_, __) => /* build your widget here */,

Developer Productivity

Flutter Hot Reload makes code changes go live in the device/simulator within a second. It’s the main reason why working with Flutter can be such fun! I mentioned it in the talk. Here is a video demonstrating it.

Flutter Hot Restart gets the app back into its initial state. That takes 3-5 seconds on my M1 Max MacBook Pro.

Plugins (Libraries)

Plugin Portal

The Flutter plugin portal is awesome! It gives you example code, popularity metrics, and code quality information.

Here is the main plugin page:

The main plugin page
The main plugin page

This is the changelog:

The plugin changelog
The plugin changelog

Here is an example program:

The mandatory example program
The mandatory example program

Here is the version list:

The version history
The version history

The score screen tells us about the code quality of the plugin:

The code quality
The code quality

Forking Plugins

Sometimes, there’s a bug in a Flutter plugin. Or we need a feature that a plugin doesn’t have. Then we can fork the plugin easily in Git. Please note that the plugin’s license needs to be compatible with forking.

Once we have the plugin forked, we don’t need to publish it. Instead, we can use the fork’s Git repository URL directly in the build file. Here’s how. Sweet!

Notable Plugins

comments powered by Disqus