Cross-platform development is undoubtedly one of the hottest topics in mobile software industry. 2019 was a year of new developments in the area and 2020 is opening with 2 clear leaders of the mobile multi-platform race. Relatively long-standing React Native and a newcomer – Flutter, have taken the top spots. I will be taking a closer look at both frameworks and their current standing.
History of React
Flutter’s story starts with the 2015 Dart developers’ conference, where “Sky” was first shown – the very first version of what later became officially known as Flutter. A stable, Version 1.0 of the framework for creating native Android / iOS apps saw its release in December 2018 at an official event.
The creators promised (and apparently delivered) a tool for creating “Beautiful, native apps in record time”. Flutter was very positively received and quickly started gaining in popularity. Our first contact with Flutter was very positive as well and convinced us to continue working with the framework.
React Native – How Does it Work?
Creating the UI
The fundamental building block in React Native is a component (React.Component). It can be a function/object with “state” and “props”, which define the effecting view. “Props’ are externally set arguments out of component’s control, and “state” is component controlled internal data.
React Native contains a library of standard UI elements with bindings to native components, used by specific OS accordingly. The hierarchical structure of the components can be freely grouped to form the declarative view.
The Data Flow
Unlike most declarative technologies, which utilize 2-way data bindings, React Native uses unidirectional data flow. At the rendering stage the parent component gets props and state as read-only, which it then can freely transform and propagate down hierarchy, but doesn’t directly mutate them. The child component receiving props data abides by the same rules and restrictions. Modifications to state (or props) don’t cause the view to refresh. That’s is done using setState method.
Dart is the official Flutter programming language developed by Google specifically for the framework. It is object-oriented, and its type system combines runtime control with static typing. With the async,await and Future type, it’s possible to code asynchronously with the appearance of synchronicity.
Largely inspired by React Native’s component based structure, flutter uses Widgets as building blocks of the application. The hierarchical structure of the app’s elements is rebuilt at each change of state. The final view is not built each time that happens. Instead, the structure serves as an intermediary for the framework to modify the visible interface.
Instead of native-like imperative style, Flutter offers declarative style relieving the programmer of creating transitions between interface states.
As for UI building, Flutter’s library is quite extensive offering ready made components/widgets complying with Material Design Guidelines. You will find buttons, text boxes with titles, or wrappers that manage the position of beams or floating buttons.
Flutter has an extensive range of ready-made, Material Design compliant widgets s. You will find everything you need from buttons, and text boxes, to wrappers, floating buttons.
To arrange components of the screen, you define component properties using containers. This causes the app’s structure to become sizable and remembering the behaviors and relationships between various containers can become somewhat problematic.
Google suggests BLoC architecture as a preferable solution in Flutter. Use cases are placed in separate classes and communication occurs via streams, with the interface publishing BLoC input events, while listening to the outputs for app’s states. The StreamBuilder widget serves as an intermediary and an interface, accepting the streamed data. The architecture is well adapted for operating asynchronously with all kinds of data flowing in at random times.
Bloc will be a familiar solution for native programmers used to working with MVVM. There are other possibilities, as Flutter also works well with Redux where state can be communicated by the components. The whole process can be simplified and the path for data shortened using the InheritedWidget. Another solution is Provider – a library for Dependency injection and app state management. You can use this eg. to provide the interface locations with all the necessary values.
Google provides a very good set of documentation, tutorials and support to help developers in implementing the solutions in their Flutter projects.
Here’s a list of popular cross-platform tools
Hot / Live reload
Installing Expo on a device will allow downloading React Native code and instantly updating existing app running on the device. The tool is not the best for production environment, but is a great support for prototyping.
Adding push notifications, libraries or Crashlytics not present in Expo SDK requires you to export a complete Exp3o project into a full version.
A browser-based simulator that allows viewing of the working app in your desktop browser window.
CLI for React Native
A tool to generate React Native projects. So far limited options available in this terminal-based program.
Using the CLI still leaves generating certificates, adding dev / prod variants or hooking up Crashlytics in your hands. You can try creating your own templates, but the React Native environment is changing so quickly that it might prove irrelevant and not usable fast. Poor solution compared to designers in Android Studio / XCode.
Several testing frameworks exist that work well withReact Native. “Jest” is available by default and is quite comfortable to use by simply putting unit tests into __tests__ and running “npm test” from command line. The only issue is the need for mocks for importing modules that are native, which often works poorly.
Releasing App Builds
Releasing builds requires operating in platform specific environments. Whether you’re working in a cross-platform or a native framework, you’re restricted to the capabilities of Android Studio/XCode.
Flutter offers plugins for Android Studio and Visual Studio Code. They support project creation, debugging and Hot Reload.
OEM Debug Tool
Dart code debugger which also works for platform specific files. Very useful for writing custom solutions.
Flutter has a plugin for checking widgets, and performing integration and unit tests. Flutter’s official support recommends Mockito testing dependencies.
Thanks to Flutter’s flavors you can set configuration for different build variants, Android’s productFlavors and schema foriOS’. After configuring them for each platform, they can be called directly in the code or Flutter CLI. You can find out more from community articles about Flutter.
The Learning Curve and Flutter
Google constantly advertises and encourages adopting Flutter. The official page offers articles, tutorials and videos covering most aspects of Flutter development.
The documentation thoroughly explains all aspects of – from UI building to testing, and is a great help for seasoned programmers, especially in explaining differences between Flutter and other frameworks.
Support for Starters
The cross-platform framework landscape is gaining popularity. Solutions producing native applications for multiple platforms keep improving in performance and quality. Flutter and React Native are emerging leaders of the x-platform race.
The market is currently very much into React Native applications. It comes not just among startups- world’s largest brands look towards cross-platform with increased interest. Framework seems to be an ideal choice for MVP.
Both Flutter and React Native build declarative views. The concept of a Component(React Native) and a Widget(Flutter) as building blocks of an app, and an unchanging state are both innovative and useful ideas. Both frameworks offer live/hot reload, drastically speeding up development process and introduction of changes.
Both frameworks are based on similar ideas. Declarative UI building allows the developer to apply different solutions for managing the app’s state.
If it works, don’t change it
Native and back-end developers switching to x-platform will need to assimilate patterns better known from web productions. Knowledge of native platforms will still be a huge advantage and improve building of applications.