Flutter vs React Native

Introduction

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.

 
Flutter Architecture

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

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.

Like React Native, Flutter provides reactive-style views. In order to optimize apps for quicker rendering and avoid performance problems stemming from the need to use a JavaScript proxy/bridge, Flutter uses the Dart programming language code, compiled ahead-of-time (AoT), running the executable code, including embedded support for all utilized widgets, on Dart VM. Flutter approach still requires that the data passed between the app and the native system is marshalled/unmarshalled. There is no costly context switch for displaying UI components, however, which greatly improves widget rendering performance. Since this is achieved by implementing all widgets in Flutter itself, the cost of the optimization is the lack of any synchronization between native operating system widgets and Flutter widgets.
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.

 
Routing

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.

 
Hot Reload

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.
React-Native also provides an ability to hot-reload JavaScript code without having to rebuild the app. React-Native apps, however, do not preserve state across reloads, so applications have to reinitialize.

FlutterReact Native
Programming languageDartJavaScript, (Obj-C/Swift and Java/Kotlin for native modules)
CompilationAoT + Dart VMInterpreter or JIT
PortabilityAndroid, iOSAndroid, iOS, Mac, Windows
UI componentsCustomization of built-in widgetsNative
Rendering performanceGoodComplex UI may require native components for native-like performance
App binary sizeLargeSmall
EcosystemEmergingDeveloped

 
Conclusion

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.

The main selling point of Flutter is the better graphics performance achieved by the elimination of proxies. In order to take advantage of it, developers need to use the Dart language and Flutter widgets. Our React Native engineers create “performance components” in native code, while using React-Native JavaScript code to glue components together and implement business logic. This allows our React-Native apps to reuse logic and large parts of the interface while exhibiting performance on-pair with native apps.

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.

More from our blog

See all posts