Flutter Part 1 - Flutter vs. Xamarin
Tommy Elliott | August 25th, 2021
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.
What is Flutter?
“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 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’s slogan - “Everything is a widget.”
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.
1 – Deployment Targets and How it Works
- Can deploy to mobile, desktop*, web, embedded devices
- Imitates the display and function of native controls
- AND provides a much broader set of widgets and features than what exists in native
- Renders into a canvas control
- Can deploy to mobile, desktop*
- Transforms code and views directly into native controls
- In some cases, lacks desired controls and features that don’t exist in native controls
- Renders native controls
*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 preview release stage and UWP is stable, and Xamarin Forms does have some web platform support in 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 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.
2 – UI Approach and Hot Reload
- Declarative UI: UI is a function of app state; display re-renders whenever relevant state changes
- Hot Reload and Hot Restart are very reliable due to the canvas layer
- Not just UI changes – almost any area of code being changed, except alterations to app plugin/package dependencies, appropriately affects Hot Reloading
- Hot Reload is stateful; Hot Restart restarts app fresh
- Fancy/slick UI experience and customization options are generally available out-of-the-box or via packages
- Imperative UI: Renders the UI; makes imperative adjustments to rendered UI based on app state
- Hot Reload and Hot Restart sometimes lose critical app state, which leads to needing a full re-deploy
- Some UI experiences with visual customizations can be done within Xamarin Forms, but other customizations can require excessive developer effort using platform-specific SDK code (wrapped in C#) to adjust native control functionality or renderers, or to create custom controls in each platform
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.
3 – Device Access and Platform-Specifics
- Access to host device features is generally available via pub.dev plugin packages, where async messages get sent between the Flutter UI layer and the platform host layer that interprets a message into native calls and a response message; native or custom C/C++ APIs can also be called via plugin
- Must-have platform-specific adaptations are applied automatically in library widgets/navigation/gestures in iOS and Android to match OS expectations, and Flutter often includes the ability to explicitly produce platform convention effects where desired; see Platform-specific behaviors and adaptations, Building adaptive apps, and these posts for more details.
- Access to host device features is generally available via the Xamarin.Essentials package or other Nuget packages, where Xamarin interfaces are usually generalized wrappers for native interfaces
- Due to use of native controls, controls work as users expect for the iOS and Android platforms, unless explicitly customized to do otherwise
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 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).
4 – Development Language and Options
- Both UI and back-end code are developed in the Dart language
- Developed in VS Code or Android Studio or IntelliJ; *each platform you target has development machine requirements (run iOS only on a Mac) and required installations
- UI is developed in XAML (like XML but with bindings) and/or C#; back-end code is developed in C#
- Developed in Visual Studio for Android and UWP with a networked Mac required for iOS (local network for debugging), or in Visual Studio for Mac for Android and iOS
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 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.
5 – History and Cross-Platform UI
- Flutter 1.0, the first stable release, was released 12/4/2018
- Flutter has been under rapid development, but is a relatively new offering
- Flutter is most robust with its MaterialApp widget as app root, based on Material Design, applicable to all Flutter-supported platforms, not just Android
- CupertinoApp is themed based on Apple’s Human Interface Guidelines, and is obligated to use a fallback font when displayed on non-Apple devices
- Widgets generally do not adapt their display to match their platform, so the decision between those two makes cross-platform app UI either themed like Material Design or Apple’s Human Interface Guidelines on every platform
- Xamarin.iOS (formerly MonoTouch) was first released 9/14/2009
- Xamarin.Android (formerly Mono for Android) was first released 4/6/2011
- Xamarin.Forms was first introduced 5/28/2014
- Much more development has gone into Xamarin
- Controls in Xamarin.Forms each display as the platform-specific native control
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.
6 – Future Expectations
- Looking to the future, cross-platform development market share for Flutter seems to be growing where all others, aside from React Native, seem to be shrinking
- Development on the Flutter library remains highly active as there is currently a lot of support for Flutter from Google and open-source contributors
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)
- “The next major version of Xamarin.Forms will [be] around September 2020 and continue to be updated through the release of .NET MAUI with .NET 6. After that, Xamarin.Forms will continue to receive priority servicing for 12 months.” (until November 2022, by which point a migration path will be available) - Xamarin
- “As an evolution of Xamarin.Forms, you will be able to use all XAML with all its existing features, and we will continue to improve XAML to help you be even more productive. .NET MAUI will continue to support MVVM while providing developers options to use RxUI and MVU.” - Xamarin
- RxUI: ReactiveUI, a functional and reactive Model-View-ViewModel (MVVM) framework
- MVU: Model-View-Update, an application architecture with single flow of state
7 – Similarities
- Top 5 in 2019 and 2020 cross-platform mobile framework usage
- Have many packages/plugins available
- Have excellent documentation and community
- Flutter - sound null safety in Dart 2.12 and Flutter 2 / Xamarin - nullable reference types in C# 8
(Flutter Part 2 coming 8/30/2021)