What is Flutter? What are its pros and cons? Why is it worth learning about and using? How does it work? How does it compare to its competition (like Xamarin Forms, which I have experience using)? How can I learn about it and start using it?
I have recently started to dig in and learn about Flutter. There is a lot to learn and so much information that I want to share, so I will get right to it and answer the obvious.
“Flutter is Google's UI toolkit for building beautiful, natively compiled applications for mobile, web, desktop, and embedded devices from a single codebase.”- Flutter. It is an open-source software development kit (SDK), maintained primarily by Google, used for developing cross-platform applications primarily for Android, iOS, Linux, Mac, Windows, and web. Flutter enables a developer to construct a very flexible and slick UI while allowing the definition for the UI and business logic to be reused to build for and deploy to multiple platforms. In a lot of ways, it’s like other cross-platform development frameworks (for me, I think of Xamarin Forms), but it has several significant differences that allow for Flutter to have more flexibility in its UI and animation capabilities.
Flutter uses an aggressive composition strategy in which everything from your top-level root application down to your tiniest UI element is a widget. Widgets can be reused in as many places as desired, and each utilized widget becomes part of a widget tree that is used to render each frame of your application’s display. Most widgets the app developer creates are composed of various other widgets, and this widget composition approach, similar to how React websites compose their UI from components, enables flexibility, consistency, code reuse, and efficient performance.
Since I came to Flutter from working with Xamarin Forms, as I continue to explain Flutter’s capabilities, I will show many equivalent details corresponding to Xamarin Forms too, which I hope helps to highlight what makes Flutter different.
Flutter:
Xamarin Forms:
*As of Summer 2021, Flutter desktop deployments for UWP are in an alpha release stage and in beta stage for WPF, MacOS, and Linux. Xamarin Forms deployments for MacOS are in the preview release stage, and UWP is stable, and Xamarin Forms does have some web platform support in the early stages too.
There is a rarely used approach where a native mobile control could be hosted within a Flutter app (think a Google Maps control), but performance for native control hosting in Flutter is slow and should (typically) be avoided. [See Rendering native controls in a Flutter app]
The canvas control in mobile apps typically takes up the full available screen space of the app (with a SafeArea widget to leave room for platform-specific needs on the top and bottom of the screen).
When iOS or Android OS updates include UI differences for native controls, Xamarin apps will typically immediately see those changes reflected; Flutter apps (wherever trying to approximate native control appearance) would need to wait for the development of an updated Flutter version that modifies the visual display or functionality in Flutter’s controls when building for that platform to reflect the corresponding platform native controls, then for the app developer to apply the updated Flutter version to the app then release the updated app in the corresponding app store. However, to use newly introduced control features outside of default settings, Xamarin apps would follow the same pattern as Flutter, except the Xamarin library update would simply wrap the new features, not having to build matching functionality.
Flutter:
Xamarin Forms:
Flutter for Web currently supports hot restart, but not hot reload. See more at Building a web application with Flutter.
Animations and transitions are much easier and more flexible in Flutter due to the flexibility of its vast widget library, the numerous ways widgets can be nested to render UI, and the way that declarative UI allows widgets complete flexibility in how they re-render given specific app state.
Flutter has several widgets specifically built to animate transitions or visual changes, either automatically or in custom ways (like AnimatedContainer and Hero widgets).
Here is an article that really brought into focus for me the impact of Flutter’s Hot Reload.
“In Flutter, you can edit anything […]. Your UI, your services, your business logic. Anything. And then you save it, the changes are synchronized to your device, and you can use them immediately. Even if you write brand new code and set a breakpoint when you save it, that breakpoint will be hit like it was always there.” - BetterProgramming.
For details on Hot Reload special cases, check this out.
Flutter:
Xamarin Forms:
Some commonly used Flutter plugins include camera, webview_flutter, geolocator, http, shared_preferences, url_launcher, device_info_plus, share_plus, connectivity_plus, path_provider, sensors_plus, and sqflite.
Flutter automatically handles things like overscroll behavior differences, iconography differences, Android back button behavior, differences in text-editing, text selection, and gestures relating to text, but leaves options for platform conventions like the positioning of switch controls at the left or right of a line in the hands of the app developer (sometimes even providing a platform-based option that follows platform convention).
Flutter:
Xamarin Forms:
Flutter for Android requires a full installation of Android Studio to supply its Android platform dependencies, although you may develop the code in other editors. [Android Setup For MacOS and Windows]. After trying out Flutter using Visual Studio Code (on both Windows and Mac machines), I am very satisfied with it as my Flutter development environment, especially after installing a few crucial extensions (“Flutter,” “Dart,” “bloc,” and “Git History”).
Flutter for UWP is in the alpha stage and requires installation of the latest Visual Studio (with the appropriate workload/tools installed). Windows setup here.
Flutter for iOS and for MacOS must be built and run on a Mac and requires installation of Xcode and CocoaPods on the development machine. While shared code Flutter development can occur on a Windows machine, and testing with hot reload can occur for Android on a Windows machine, Flutter building, and testing and signing for iOS and for MacOS must occur from a Mac. iOS setup here.
Flutter:
Xamarin Forms:
Apart from the must-have platform-specific interactions and a few widgets with a platform-based display option, widgets generally do not adapt their display to match their platform. Typically, the decision between either MaterialApp or CupertinoApp near the top of your widget tree makes cross-platform app UI either themed like Material Design or Apple’s Human
Interface Guidelines on every platform, unless you write two versions of UI to best meet platform-specific display expectations or use non-standard UI. From what I have seen in various discussion threads, it seems that MaterialApp is both more robust (fewer bugs) and more widely used with Flutter than CupertinoApp is, so unless you are quite certain you want to make every platform use controls that look like native iOS controls, I would advise using MaterialApp, at least while starting out with Flutter.
There are some package attempts like flutter_platform_widgets to make it easier to use MaterialApp and corresponding widgets for some platforms, and CupertinoApp and corresponding widgets for others, but in my review of those approaches, it severely complicates the UI development and essentially equates to writing two versions of much of the display, which I would generally try to avoid.
Flutter:
Xamarin Forms --> .NET MAUI:
Microsoft’s future plan for Xamarin.Forms is to incorporate it fully into .NET 6 (November 2021) and beyond as .NET MAUI (Multi-platform App UI), for an even more cross-platform development approach (this will include MacOS as a target in addition to Android, iOS, Windows, Linux)
BOTH:
Why is Flutter worth learning about and using? We have already seen some details about what it is and how it works, and I have brought up some great aspects of Flutter, but I would be remiss if I did not bring up some vibrant app examples for you to see in action. Luckily for us, a
development team named gskinner has built, for public review, a set of open-source examples made specifically to showcase some of Flutter’s incredible UI capabilities. You could even explore their code if you so desired.
Check out these high-profile real-life apps created with Flutter. There’s also a website to showcase and make searchable thousands of apps built with Flutter, some of which are open-source and some of which are templates.
Mobile/Desktop Flutter App:
Web Flutter App:
Web rendering options:
One of the things that makes Flutter architecture unique among cross-platform frameworks is that it brings a rendering layer into the framework itself. That gives the opportunity to eliminate the inherent UX constraints in either native UI or wrappers for commonalities among multiple platforms of native UI while also putting more burden on the framework (or community) to provide the necessary building blocks for cross-platform app user experience (UX).
Another thing to notice here is that in Mobile and Desktop targets, Flutter includes the Engine layer, which connects to the device operating system for key functionality, and Embedder layer, which handles platform-specific details and connections, whereas in Web targets, the OS is inaccessible, and the only embedding needed is a translation layer into browser-compatible content and interactions.
“To perform layout, Flutter walks the render tree in a depth-first traversal and passes downsize constraints from parent to child. In determining its size, the child must respect the constraints given to it by its parent. Children respond by passing up a size to their parent object within the constraints the parent established.” — Flutter
“Constraints go down. Sizes go up. Parent sets position.” — Flutter
The tree in this diagram represents the widget tree for the app, where the top is the app’s root widget, and the bottom are the leaves (widgets without children). This approach allows the layout process to be both efficient and intuitive.
Flutter App:
The whole app is built using Flutter: “Everything is a widget.”
Flutter Module in Native App:
Flutter module imported into existing native Android or iOS app to render a part of the app’s UI in Flutter (or just to run shared Dart logic)
Note that step 7 here can be done mostly while the app is running to get immediate insight into the impact of your changes; just hot restart after modifying used packages.
Machine setup instructions: https://flutter.dev/docs/get-started/install
IDE setup instructions: https://flutter.dev/docs/development/tools/vs-code
Instructions for new app creation: https://flutter.dev/docs/get-started/test-drive?tab=vscode
Sources and info on multiple device simultaneous launching/running/debugging:
https://github.com/flutter/flutter/wiki/Multi-device-debugging-in-VS-Code
https://www.jacoboakes.com/flutter_multiple_device_debugging/
https://stackoverflow.com/questions/51669258/flutter-hot-reload-to-multiple-devices
Hot Reload and special cases: https://flutter.dev/docs/development/tools/hot-reload#special-cases
This image shows a glimpse at code for a basic Flutter app.
Within the bloc package, there are entities called blocs and a subset of blocs called cubits. With a bloc, it receives events via a stream from the UI and sends states via a stream to the UI. With a cubit, it receives individual calls to its functions from the UI (not via a stream) and sends states via a stream to the UI.
Info about state management in Flutter:
https://flutter.dev/docs/development/data-and-backend/state-mgmt/intro
Sources and additional details about BLoC:
https://www.didierboelens.com/2018/08/reactive-programming-streams-bloc/
https://bloclibrary.dev/ (also source of bloc image)
https://bloclibrary.dev/#/coreconcepts (also source of cubit image)
https://bloclibrary.dev/#/flutterbloccoreconcepts
https://github.com/tenhobi/flashcards/issues/12#issuecomment-373922966 (github issue summarizing a referenced 2018 Dart conference BLoC video's concepts with screenshots and explanations)
https://pub.dev/packages/flutter_bloc/example
Some potentially useful related packages:
https://pub.dev/packages/bloc_code_generator
https://pub.dev/packages/form_bloc
Videos to learn about BLoC in Flutter:
https://www.youtube.com/watch?v=toPtm6eyyeE&list=PLptHs0ZDJKt_T-oNj_6Q98v-tBnVf-S_o&index=3 (Bloc core concepts – streams, blocs, cubits)
https://www.youtube.com/watch?v=NqUx-NfTts4&list=PLptHs0ZDJKt_T-oNj_6Q98v-tBnVf-S_o&index=4 (Flutter Bloc concepts – BlocProvider, BlocBuilder, BlocListener)
https://www.youtube.com/watch?v=kLDfhamoqe0&list=PLptHs0ZDJKt_T-oNj_6Q98v-tBnVf-S_o&index=5 (BLoC architecture - Presentation, Business Logic & Data Layer + Model, Repository, DataProvider)
Detailed explanations and examples using both provider alone and BLoC approaches:
https://www.miquido.com/blog/flutter-architecture-provider-vs-bloc/
This is the suggested folder structure for a Flutter App using BLoC for state management.
lib/
business_logic/
(optionally: blocs/ and cubits/) - note that the VS Code extension “bloc” uses these folders
data/
data_providers/
models/
repositories/
presentation/
(optionally: animations/ and pages/ and widgets/)
main.dart
…platform folders, packages configuration, etc.…
To illustrate the data flow for a user interaction that makes a web request, let’s consider a user starting a Flutter App that shows the weather for a tapped city, then tapping a button to get the weather for Chicago; the following process occurs.
0) [main.dart] App starts up
1) [presentation] Show initial app state and receive the user interaction when they tap the button for Chicago weather
2) [business_logic] Communicate the Chicago selected event to the business logic component (aka bloc), and the bloc both calls the repository request for the Chicago weather model and sends a loading weather state to the presentation layer
3a) [presentation] The presentation layer builds and presents the display for the loading weather state
3b) [repositories] The repository request makes a data provider request for a particular data source’s raw data; there may be multiple data providers communicated with during a single repository request
4) [data_providers] The data provider executes the http get web request to a public weather API, and returns the raw response data to the repository code as its result, or throws an exception
5) [repositories] The repository layer handles any failure or uses a factory function on the model class to create a model instance from parsing a specific data source’s format of raw response data.
6) [models] The model factory function creates a model from the raw data
7) [repositories] The repository fine-tunes the model as appropriate and sends it as the response to the bloc
8) [business_logic] The bloc sends either a failure state or weather loaded state to the presentation layer
9) [presentation] The presentation layer builds and displays the appropriate UI for the new state (either a failure display or the Chicago weather details display)
Folder structure and example flow ideas based on video at:
https://www.youtube.com/watch?v=kLDfhamoqe0&list=PLptHs0ZDJKt_T-oNj_6Q98v-tBnVf-S_o&index=5 (BLoC architecture - Presentation, Business Logic & Data Layer + Model, Repository, DataProvider)
Use the test and bloc_test packages and optionally the equatable package for “==“ override to comparison by values between instances of types that extend Equatable, which can be good for state objects.
Testing info based on video - https://www.youtube.com/watch?v=cVru6Gy4duQ&list=PLptHs0ZDJKt_T-oNj_6Q98v-tBnVf-S_o&index=6 (BLoC testing) and - https://pub.dev/packages/bloc_test
DevTools and other language features provided by Dart and Flutter in your IDE
Also, just as a sidenote, in Dart, access modifiers like private/internal/protected don’t exist, so everything is public, except when a top-level or member field identifier starts with an underscore, that makes it private to its library, which is by default the dart file it exists in.
Sources regarding DevTools and many other features provided by Dart and Flutter:
https://dartcode.org/
https://dartcode.org/docs/debugging-commands/ (a list of available debugging commands with explanations, also the source for the inspect widget gif)
https://flutter.dev/docs/testing/debugging
https://flutter.dev/docs/development/tools/devtools (collection of links about getting started with the DevTools)
https://flutter.dev/docs/development/tools/devtools/network
https://flutter.dev/docs/development/tools/flutter-fix
Sources for release deployments info:
https://flutter.dev/docs/deployment/cd
https://pub.dev/packages/flutter_appcenter_bundle
https://developer.android.com/platform/technology/app-bundle - Android App Bundle (instead of APK)
https://flutter.dev/docs/deployment/android#test-the-app-bundle
https://developer.android.com/studio/command-line/bundletool#deploy_with_bundletool
https://developer.android.com/studio/publish/upload-bundle
https://flutter.dev/docs/deployment/ios
https://flutter.dev/docs/deployment/web
Flutter Pros:
Flutter Cons:
https://github.com/flutter/flutter/graphs/commit-activity — data showing continued effort and support from Google and open-source contributors for improving Flutter
https://betterprogramming.pub/why-flutter-isnt-the-next-big-thing-e268488521f4 — some downsides to Flutter
https://medium.com/@carlolucera/why-flutter-may-be-the-next-big-thing-15ccf6a9c358 — some counterpoints showing upsides to Flutter
https://medium.datadriveninvestor.com/flutter-engage-flutter-2-2b4e8dde016f — Q&A with Flutter leadership (3/4/2021) with the following quote regarding SEO: “SEO is something we are looking into, but right now if you are building a website that needs SEO, flutter is not a good choice”
Flutter’s main selling points include:
Also noteworthy, though mostly a side effect of the above points, Flutter has a very high and growing adoption among the cross-platform development community.
If you’re considering giving Flutter development a try, do it. Flutter is here to stay, and my bet is that you’ll enjoy creating with it, and you’ll be happy with the UI you can create, and you’ll be happy how quickly you can iterate on changes. You may even enjoy learning about it, considering the variety of resources that teach about it.
Thanks for reading, and I hope I helped you learn something new.