In May of 2017, Google released Flutter – an Open Source mobile framework for creating native apps on iOS and Android. Flutter joined a list of cross-platform development technologies, which already includes several popular solutions including React Native, Xamarin, Ionic and several others.
Engine written in C++, provides low-level rendering support using Google’s Skia graphics library. Engine interfaces with platform-specific SDKs provided by Android and iOS.
Foundation library written in Dart, provides classes and functions used to construct Flutter applications, such as APIs to communicate with the engine.
Flutter architecture diagram
Widget represents an immutable description of a part of the user interface. All graphics, including text, shapes, and animations are created using widgets. Flutter widgets are either stateful or stateless. Complex widgets can be created by combining simpler ones. Flutter contains two sets of widgets – Material Design for Android and Cupertino for iOS.
Flutter can access platform services and APIs including storage and sensors through packages. Flutter Libraries allow implementing platform channels for calling native functions from Dart.
Widgets are organized in tree structures. A widget containing other widgets is called parent Widget (or Widget container). Widgets contained in a parent Widget are called children Widgets.
A Flutter context is a reference to the location of a Widget within the tree structure. Context is associated with a single widget. If a widget ‘A’ has children widgets, the context of widget ‘A’ will become the parent context of the direct children contexts.
To defines the behavior part of a StatefulWidget instances, Flutter uses State. Changes applied to widget’s state, force a rebuild. State of a widget is associated with a context. The context won’t change even when the widget tree does. The context to state association is the final part of Flutter widget mounting process, making state directly accessible through the widget’s context.
In Flutter, each Widget is uniquely identified. This unique identifier is defined by the framework at the build/rendering time. This identity corresponds to the optional Key parameter. When omitted, Flutter will generate automatically.
A Route is an abstraction for a “screen” or “page” of an app. A Navigator is a widget that manages routes. A Navigator pushes and popes routes to help a user move from screen to screen. There is no direct way of accessing state of widgets from routes other then the current. State can be persisted by writing it out to PageStorage and reading it back.
One interesting Dart feature is the stateful hot reload. Flutter developers could fix a bug in the app code, and continue debugging it further, after a reload.
AoT + Dart VM
Interpreter or JIT
Android, iOS, Mac, Windows
Customization of built-in widgets
Complex UI may require native components for native-like performance
App binary size
Since Flutter uses a proprietary set of widgets, it is more resilient to framework and OS update issues. Updating React-Native projects often requires having to manually resolve multiple compatibility problems.
At this point in time, we feel that Flutter would be most useful to the companies already using Dart for web frontend and/or services development. However, as both Flutter and the ecosystem mature, it might become more of a standard rather than a niche platform.