Nowadays, apps are everywhere and we can find an app for almost everything. These apps can run on mobile, on the web browser or on the desktop. We can find apps that target a single system and ones that run on multiple systems. On the developer’s side, targeting multiple systems can be achieved in different ways: write an app for each targeted system using the native SDKs, create a progressive web app (PWA) or use a cross-platform framework. The second and third ways allow to share a single codebase, and thus, reduce the quantity of code and technologies to learn. The main different between a PWA and a cross-platform app is that the former has access to only the browser’s API while the latter has access to the APIs provided by the native SDKs. Among the many cross-platform frameworks available, one seems to attract a lot of developers, which is Flutter.
The following article highlights the current features of the Flutter framework and shows how to quickly get started.
Native cross-platform with desktop support
Flutter officially supports the following platforms: iOS, Android, the web and desktops (Windows 10, Linux and macOS). This means that a single Flutter codebase can be run on all supported platforms, which makes it a very interesting cross-platform framework. Of course, there are some cases where platform specific code is necessary and Flutter provides documentation on how to deal with this.
In addition to supporting both mobile and web, which is already a big feat, Flutter even supports Desktops: Windows (since version 2.10 , macOS and Linux (since version 3.0). It is the default choice for future Ubuntu desktop apps. The following screenshot taken from flutter.dev show some apps running on different platforms.
A framework that is both native and cross-platform can seduce many developers, but this is not enough unless it is accompanied with powerful tooling and editing support. Fortunately, Flutter provides them as we’ll see in the next section.
Powerful tooling and multiple IDEs support
The Flutter framework allows for smooth and easy developer experience (DX), thanks to the Flutter SDK tooling and support of different IDEs.
The first nicety that we can note is that The installation of the SDK is well documented and straightforward. We’ll also surely enjoy the availability of a cli (command line interface) that allows to create and build projects from the command line. Once the SDK is installed, we can quickly create an app and test it on a browser, thanks to web support, without requiring to install additional desktop or mobile SDKs. Of course, those SDKs can be installed later and you can run
flutter doctor to check missing items in your setup.
On of the things that
flutter doctor also detects, are the installed IDEs. In fact, Flutter currently supports three popular ones: Android Studio (or IntelliJ), Visual Studio Code and Emacs. My personal preference is Visual Studio Code but you’re free to use the one that you like. When you develop your project using an IDE, you start noticing that the modifications are applied on the fly to the running app as soon as you save your file. This outstanding feature is called “Hot Reload” (you can check out a demo here). Even native mobile SDKs fail to provide this feature in such a level.
We can also add third party libraries to our project by registering them in the ‘pubspec.yaml’ file located at the root of the project. All the available libraries can be explored from an elegant website called pub.dev. In there, you can search for libraries, read documentation as well as many other useful information such as the supported platforms and the popularity. The screenshot below illustrates a glimpse of a package page in pub.dev.
This quick overview of the Flutter DX highlights attracting and powerful features. In addition to that, the declarative programming paradigm and the Dart language used by Flutter form a powerful combination. We’ll see more of that in the next section.
Declarative programming and the Dart language
Flutter embraces declarative programming. This means that the UI is defined with code, that tells what it contains rather than how to build it (in that case, we call it imperative programming). In declarative UI programming, the dynamic content of the UI is managed by an object called a state. When the state changes, the UI automatically updates to reflect the current state. This type of programming allows for more predictable and readable UIs. Even the iOS and Android SDKs started providing declarative UI libraries, namely SwiftUI and Jetpack Compose, to replace their old imperative ones. The code snippet below shows how to accomplish the same effect with imperative and declarative styles. Do you see the difference in terms of expressiveness ?
// Src: https://docs.flutter.dev/get-started/flutter-for/declarative // Imperative style b.setColor(red) b.clearChildren() ViewC c3 = new ViewC(...) b.add(c3) // Declarative style return ViewB( color: red, child: const ViewC(), );
If you’re interested in learning further about declarative programming, you can find many resources on the internet such as the one provided by the Flutter team. By the way, in Flutter, any UI element is called a Widget. That’s why some say that everything is a widget in Flutter.
The programming language used by Flutter is called Dart. It has evolved so much since the release of Flutter that it be can compared, in terms of features, to modern languages such as Swift, Kotlin, TypeScript or C#. Here are some notable features: null safety, functions as first-class citizens, Object oriented programming, high level asynchronous programming and many more. These features allow for safer code which is free from null pointer exceptions and is compatible with declarative UI programming. We can even learn and play with Dart online using DartPad. As a big bonus, since Flutter supports the web, DartPad also supports creating Flutter projects online by clicking on new pad and choosing Flutter. So why not give it a chance 😊.
We may be wondering now how Flutter added web support so quickly. This is in part thanks to its rendering pipeline. The next section provides a brief introduction to it.
Platform agnostic rendering pipeline
The rendering pipeline proposed by Flutter is novel compared to the existing frameworks. In fact, other frameworks rely either on rendering native UI elements which may be hard to deal with in a cross-platform context, or on rendering them using a web-view which have poor performance. Flutter draws components using its own routines on a native draw area (that we usually call a Canvas). More specifically, Flutter uses the Skia library that provides common 2D APIs. This means that Flutter can theoretically support any platform as long as Skia supports it. Another corollary is that Flutter has more control over the rendering of UI components and is thus able to implement tailored optimizations for rendering Widgets.
There is one drawback with how the rendering works. Indeed, since we cannot reuse native UI components, they must be developed from scratch for Flutter and they will only mimic their native equivalent. Hopefully, Flutter’s community has already provided many high quality UI component libraries. The most notable ones are the Material library, Cupertino library that faithfully reproduces the iOS style and fluent_ui + flutter_acrylic for a Windows desktop UX.
One important thing to note is that when you use a UI component library, the app will have the same rendering on every target. So, for example, if you use the material library, it won’t show with a Cupertino style on iOS, but as material components. If this behavior is not desired, we can imagine two techniques to render platform specific components in a single codebase. One of them consists of executing specific UI code depending on the current platform as shown in this article. The drawback of this method is that is may become cumbersome for the developer because it will require more platform specific code, more code branching and more duplicated UI code. Another interesting way of rendering platform specific UI components would be to use a library that takes care of rendering platform aware widgets. That’s what flutter_platform_widgets tries to achieve by providing a set of widgets that adapt their rendering depending on the current platform (as illustarted below). This library is made possible thanks to the contribution of the huge Flutter community.
Speaking about community, Flutter has one of the most active ones. I’ll show this with some numbers in the next section.
A very active community
An active community means that developers and companies can confidently use the Framework in their projects. One of the metrics used is the popularity, and “Flutter is the the most popular cross-platform framework in the world” as cited by the Official Flutter community page which relies on the “JetBrains 2021 State of Developer Ecosystem survey”.
With 138k stars on GitHub, 178k followers on Twitter and 60k members on Meetup (at the time of writing), any developer can be reassured to find support on the internet. They can also subscribe to great YouTube channels. I personally recommend the Flutter Widget of the Week playlist and the Flutter Community channel.
These numbers and facts show that Flutter is a viable solution for long term projects because we can be confident that the Framework will keep getting updates and improvements. The next section summarizes all what has been mentioned in this article and provides some concluding words.
Summary & conclusions
This article provided some key features of the Flutter frameworks that makes it one of the best choices for cross-platform front development. It highlighted many features such as the large quantity of supported operating systems, the tooling, the developer experience, the rendering pipeline and the community. It also are many other features that were not mentioned such as accessibility. This makes Flutter a reasonable candidate to consider for you future project or to at least to try out, especially if we want to target multiple platforms.