For more than ten years now the development of mobile applications has been going on, and the eternal question remains: what to use - mobile native development or a cross-platform solution? Of course, everything depends on the purpose of the project. In fact, definitive markers for choosing between native and cross-platform do not exist.
At the moment, the market of operating systems for mobile devices (phones, tablets, smartwatches, TVs, etc.) has formed and is focused on two main platforms - Android and iOS.
There are many technologies for creating cross-platform applications for mobile systems, among them: Xamarin, PhoneGap, Ionic, React Native and so on. It is known that in the field of developing cross-platform mobile applications there is enough space for many options. Of course, different technologies have their pros and cons.
Google suddenly announced another cross-platform development system for mobile devices, Flutter with the Dart programming language. This system allows you to develop applications for Android, iOS and the new open-source operating system Fuchsia. So what are the main differences between Flutter and existing systems:
- Running speed of applications is fast, so Google has achieved a high rendering speed.
- The applications have a single code base for iOS and Android, which means that when editing or doing a bugfix, there is no need to do double work.
- The application looks native and absolutely identical on the Android and iOS platforms. This avoids double elaboration of user interaction scenarios. But you can implement and customize the interface for each platform.
- If there is a need, the application is easy to integrate with Google Services and Google Cloud.
- For developers, there are very cool tools based on Android Studio and Visual Studio Code, excellent documentation, and great support on the public discussion forums.
Naturally, the question arises, is it worth studying this new Flutter platform in addition to the new programming language Dart? Let’s consider this issue in more detail.
Why cross-platform development on Flutter?
Flutter is a new but very promising platform that has already attracted the attention of large companies that have recently launched applications.
On December 4th, 2018, Flutter 1.0 was released at the Flutter Live event, denoting the first "stable" version of the Framework.
This platform is interesting for its simplicity compared to the development of web applications, and the speed of work on a par with native applications. High application performance and development speed are achieved through several approaches:
- Unlike many well-known mobile platforms, Flutter does not use JavaScript in any form. As a programming language for Flutter, Dart was chosen, which is compiled into binary code, thereby achieving a speed of operations (almost) comparable to Objective-C, Swift, Java, or Kotlin.
- Flutter does not use native components in any form, so you do not have to write any layers for communication with them. Instead, like game engines (and games have a very dynamic UI), it draws the entire interface on its own. Buttons, text, media elements, background - all these are drawn inside the graphics engine in Flutter itself. Note that the “Hello World” Flutter application only takes up a few megabytes.
- Flutter uses a declarative approach inspired by the ReactJS web framework based on widgets (in the world of the web called components) to build the UI. For an even greater increase in the speed of the interface, widgets are redrawn only when something has changed in them (similar to how it works in the web front-end).
- In addition to this, the framework has a built-in Hot-reload, a feature which is so common on the web, and was not available on native platforms.
For the practical benefits of these factors, you can read this article by an Android developer who rewrote his application from Java to Dart and shared his impressions.
But as you must recognize, there are some minuses of Flutter technology as well:
- The final installation package is larger than native development.
- The interface is created using code, which makes the split between logic and designs much smaller.
- There are fewer libraries than for native development, although their number is constantly increasing.
- This is new technology and few specialists have mastered it yet.
A few bold concepts underlying Flutter bring new ideas and opportunities to the development. Fast, almost intuitive user interface creation makes prototyping and UX experiments easy and affordable for everyone.
According to our leading Flutter expert, “For many factors, a cross-platform approach may be suitable for simple applications that provide, say, a basic set of services/functionality. And this approximately makes up 80-90% of the mobile application market. Naturally, the competition at the moment is too great and every product wants to stand out from the competition. Often this is done through a more sophisticated and thoughtful UI/UX using wow-effect. Flutter can provide all this at the moment. Speaking about more custom things and integration in the application, nuances, and limitations may arise due to the current state of the platform."
About Dart
Dart is a programming language in which we have to write applications under Flutter. It is very simple, and if you have experience with Java or JavaScript, you will quickly learn it.
In the summer of 2014, ECMA International, standardization of information and communication technologies organization, approved the specification ECMA-408, which standardizes the syntax and semantics of the Dart language, as well as the composition of basic libraries and related language technologies. Since then the Dart language is the official standard of ECMA.
Let’s see the main Dart features:
- Simple and easy to learn syntax, natural for programmers in JavaScript, C, and Java.
- Delivering fast startup and high performance for all modern mobile systems.
- Ability to define classes and interfaces that allow you to use encapsulation and reuse existing methods and data.
- Optional use of types, whether or not static types are decided by the developer. Specifying types allow you to simplify debugging and error detection and makes code clearer and more readable. Additionally, it simplifies refinement and analysis by third parties.
- Supported types include different types of hashes, arrays and lists, queues, numeric and string types, date and time types, regular expressions (RegExp). It is also possible to create other types.
- To organize concurrent execution, it is best to use isolate attributes whose code is executed entirely in isolated space in a separate memory area, interacting with the main process by sending messages.
- Support for the use of libraries that make it easier to support large web projects. Third-party feature implementations can be connected as shared libraries. Applications can be broken down into parts and the development of each part assigned to a separate team of programmers.
- A set of ready-made tools to support Dart development, including implementation of dynamic development and on-the-fly (edit-and-continue) code debugging.
- Ability to create homogeneous systems that cover both the client and server-side. Using the same language and tools for client and server components simplifies the coding process and eliminates the constant change of context.
Where to start
If, after reading about Flutter, you want to learn this library, perhaps it is best to start with the step-by-step lessons posted on the Google Codelabs resource. In particular, here is a guide on basic working methods that demonstrates the process of creating a user interface. Here you can find guidance on using Firebase features in Flutter-created applications.
As for any standard learning cycle for new programming languages here is a recommended sequence for Flutter and Dart:
- Install Flutter SDK and configure it in your favorite IDE.
- Download code for “Hello World”, review it and run it.
- Make a deep dive into Dart syntaxis and the concept of programming.
- Learn Flutter Layouts and Widgets.
- Learn Flutter Data and Backend.
- Improve areas where your project needs the application of your deeper knowledge.
A good example of a basic Flutter course is the free course on Udacity. The lessons are divided into two chapters, and each of them will take a few hours.
“Everything is a widget”
A key feature of the system architecture is that all widgets, as well as the components responsible for rendering widgets on the canvas, are part of the application, not the platform. It is the lack of need for context switching and the use of "bridges" that gives a performance boost.
According to Flutter documentation, a widget can define:
- a structural element (like a button or menu)
- a stylistic element (like a font or color scheme)
- an aspect of the layout (like padding)
Widgets can be either a StatelessWidget or a StatefulWidget.
An example of a stateless widget in an application might be the main app widget that extends from StatelessWidget class and runs by void main()=>runApp(). This is the root of the application. Inside of it, there are all the elements that are required for rendering by overriding the build method.
Any static widget is an inheritor of the StatelessWidget class. You just need to override the build method and collect the necessary element in it. Flutter promotes composition. Do not expand an existing item to create a new one. The construction of the interface occurs by passing the class constructor to the corresponding field with the initialization of the arguments. Dart supports optional method parameters, which gives you the flexibility to create a UI.
Stateful widgets are stated widgets that support redrawing when their state changes. To make such a widget it is necessary to inherit from StatefullWidget and create an inheritor class State <T>, which is the state of the widget and is responsible for what the user sees on the smartphone screen. The state of the widget is changed by calling the setState () {} method. When changing an object on the screen, the framework itself will determine the minimum necessary redrawing of the UI.
Themes for Android and iOS
Usually, you need to make Android apps look different than iOS apps (and vice versa). The differences lie not only in the colors of the interface elements but also in the size and style of the widgets. That is, the application requires customization of the user interface for each platform.
The correct display of application interfaces on different platforms is possible with the help of themes. Customization of applications in Flutter is made possible by the condition in the code, where you can recognize under which platform (Android or iOS) the application is currently running and execute the code for this platform.
The creators of the Flutter platform offer developers a wide catalog of ready-made widgets. It contains two sets of elements, Material Components and Cupertino, which look native to each platform. Cross-platform widgets are also available. Their appearance and behavior are identical on iOS and Android devices.
Testing and Debugging
There are three test methods for applications in Flutter: unit testing, widget testing, and integration testing.
Here is a table for comparing testing modes from Flutter application testing documentation that can help in the decision about which testing method you need to apply for specific cases in your project.
Using unit testing in Flutter is basically similar to other well-known unit testing systems designed to test the functionality of a class, method or function.
Widget testing allows you to create a test for a specific widget separately from the entire application, which greatly simplifies testing and allows you to create a hierarchical testing structure. Sometimes it’s quite difficult and cumbersome to describe testing within the application; in this case, Flutter allows you to test one widget first, and then test it in the general application.
Integration testing allows you to test the operation of the entire application and is already performed in the emulator iOS or Android. By correctly combining the three types of testing, you can achieve very good test coverage and avoid further testing problems when adding new functionality.
But that’s not all since Flutter is really a wonderful platform and allows continuous integration. Flutter continuous integration can use Fastlane, Travis, Cirrus, GitLab CI/CD, Codemagic CI/CD, Bitrise, etc.
All the same, even in Flutter, it is recommended to test for each platform separately. Testing for one platform does not guarantee that it will work equally well on another platform.
Conclusion
Fast, almost intuitive user interface creation makes prototyping and UX experiments easier than ever and accessible to everyone.
In general, we can say that Flutter is suitable for 80 percent of applications that need to be launched simultaneously on iOS and Android. This platform can be recommended for creating rapid prototypes, as development is really fast. It can also be recommended for working with standard user applications to save budget and time, so as not to separately support native code for Swift and Kotlin. As for more complex applications that require a large specificity of mobile operating systems, Flutter will also cope with this task. The only question is the amount of time and effort that will be required for such a solution.
One thing can be said now, Flutter will develop and strengthen its position every year.