Flutter: expectations and first commercial experience

Having created my first app using Flutter, I weigh up the technology’s pros and cons against the other big cross-platform development contender — React Native
Flutter: expectations and first commercial experience
Just recently we have launched our first commercial project in Flutter, and we have to admit that after the release we had the longest retrospective ever. Having our previous experience mostly in React Native, we decided to analyze as fairly as it’s possible all that thousand of differences that these technologies have.
Remember the hype that React Native caused 2 years ago - how many giants started using it - Tesla, Facebook, Skype and a long list of other big names. After their investigations on this technology in 2016, in mid-2017, we have got hundreds of apps from Fortune 500 companies on React Native.
Two years later we have a typical for all hype trends situation - when big guys have another favorite - this fact immediately affected the IT community and decisions to use React native stop being so easily taken as in 2017 or 2018. No one says, that the technology is dead, but the absence of positive dynamics speaks for itself. A lot of experts and technology trends observers noticed, that the companies, which adopted React Native, did not migrate their ecosystems to this technology - they just give it a try in particular autonomous modules. Further, some of them found out that React Native did not work well for all businesses, and in 2019 they abandoned it, however, a lot of companies still use it. 
Meanwhile, in mid-2017 on the Google IO developers conference, a new star was born. Though it was an alpha version of the cross-platform technology for mobile apps, with ultimately limited capabilities, in counted months the best brains of our planet released ready for production Preview 2:

  1. Stable products with 50+ millions of users build by giants as Alibaba, Tencent and, to be expected - GoogleAds.
  2. The focus of pixel-perfect apps was changed from Android Material design to iOS products.
  3. Significant popularity on GitHub - open-source Flutter entered a list of top 50 popular repositories.
  4. The size of an average app’s package reached just 4.7 Mb in release mode.

As a company that tries to keep abreast of all technological trends, we simply had to study this technology. However, it took several months before we found a suitable commercial project and a right developer for our first Flutter pilot. Obviously, we had a bigger buffer in the project schedule, but these risks were worth it.
So what is Flutter in a nutshell?
An open-source from the beginning SDK,  powered by Google for extremely fast development of Android and iOS apps with a lot of shared code. Just as in Xamarin or React Native, you’ll still need a macOS machine for iOS builds because Flutter works in conjunction with iOS and Android SDKs. The installation for Android went smoothly via “flutter doctor” command, unlike iOS setup, where we found several pitfalls in the beginning.

  1. Some are stopped by the fact that Flutter is written in the Dart language, created by Google itself. In practice, it turned out that if you know JS, Java, Kotlin, Swift, or C # sufficiently, then Dart is the last thing to worry about.
  2. Native ARM code, compiled by Flutter ahead-of-time instead of runtime gives a better performance due to the absence of JS bridge. But also this means that updates over-the-air with a new JD bundle do not work in this case.
  3. Unlike Xamarin or React Native, Flutter draws the UI components on a screen canvas instead of wrapping on top of the iOS/Android native UI components.  To do this, Google decided to use Skia - C++ 2D graphics library, which is also used in Google Chrome, Android, Chrome OS, Firefox OS, and many other products under a BSD license.
  4. Flutter, just as React Native is also based on reactive programming. That means that functions can’t change the UI components directly. The UI is re-rendered every time due to changed properties or variables affected by the input of the user.
  5. There is a super convenient hot reloading feature in Flutter - when you change something in the code editor and save - the UI refreshes immediately on the iOS simulator or Android emulator. 
  6. Extensibility with third-party plugins, that wrap platform-specific features not covered by build-in classes, like video, storage, camera, ML, etc. Also, this allows adding new custom-drawn UI components.
  7. Flutter allows to relatively easy write a platform-specific code in several ways: 

a) writing native plugins for platform-specific functionalities

b) executing the different code after checking PlatformisIOS/Platform.isAndroid in case of difference in .dart file logic or difference in the UI.
8. For typical apps, performance is not a problem, especially in the release mode (debug mode obviously slows down the virtual machine, running Dart code). The UI of Flutter is written in low-level C++ library, while other functionalities use native counterparts. But still, the less redraws in parts that depend on the changed state you do - the better the app works.
9. The best current approach to write and build Flutter apps is to use text editors like Android Studio, VSCode or Intelli J, however, actually you can literally use ANY text editor in combination with flutter command. The difference here is the autocompletion feature, along with some debug tools and spare that you need to use the command-line to compile/run the apps.
But words are words, and to get the visionary understanding of what Flutter actually is, and feel the performance in comparison to React Native - just download the Flutter Gallery app from Play Store. 
Why Yes:

  1. Predictable rendering. As far as Flutter creates its own UI instead of wrapping around native components, that means that something rendered on your test iPhone will be rendered exactly the same on the Android and any other iPhone. Literally. This is the main difference between Xamarin or React Native where UI components and properties are supported only for one platform, while on the platforms they may be rendered in a bit different way to their counterparts. From QA prospects this means that you still need to check the app on multiple devices before release, but with Flutter, you are much safer. The main risk here is the usage of third-party plugins mapping to underlying platform-specific components. Usually, it is related to such features like video/audio, in-app billing, and notifications. may happen that you will have to write a platform-specific code to fix some issues.
  2. Hot reloading. Saves precious minutes, nerves and cuts off boring manipulations by just pressing ⌘+S in the editor. However, when you change plugins, navigation, logic or state of initialization and assets, you still need to use build-wait-run-wait-test-start process.  Most of the UI changes in Flutter are immediately applied, but in apps, with heavy UI this is exactly where a developer has to dedicate a lot of time. 
  3. The overall principle of Flutter (and React Native) - is the usage of small reusable components that react to a change of state.  Sure, reactive apps also can be built with Android and iOS development tools, but in Flutter it looks more natural. The difference is that in Flutter this is the core of technology, no need in third-party mindware and libraries, working together sometimes in a weird way.
  4. Right language. Consistent and complete language for asynchronous programming, powerful enough to stay in one row with Swift, Java or Kotlin. At the same time - Dart is simple. At least more simple than JS.
  5. Built-in support for both widget testing of UI and interactions, and logical unit testing allows you to check the correctness of values of widget properties, find child widgets and a widget tree, scroll gestures and send taps. Other options are described in the official docs for Dart and Flutter.
  6. In addition to the above, built-in support for theming of the app’s UI, literally of each aspect. Simple setting of theme property of the root MaterialApp object with a few lines simplifies the hardest thing about creating dark/light themes - picking the right color.
  7. Last but not least. As an advantage of any cross-platform technology - you keep both iOS and Android app aligned during the whole process. No headache about coordinating the release dates, feature parity, mismatch of performance and expectations of the app on the platforms. With Flutter, you avoid a situation when the app on one of the platforms is left behind. 

Why maybe

  1. Tried once a technology is not something that can be judged categorically, but even after our first experience, we found some things that are rather in a ‘grey zone’ comparing to previous experiences.
  2. Because of painting the UI in its own way, Flutter does not create native components.  Though in the second version it does a really good job in replicating Android material Design and Cupertino library. To be precise, that means:

b) If iOS 13 change the rendering way of UISwitch or a segmented control while your Flutter app uses CupertinoSegmentedControl or CupertinoSwitch  - the app will look the same right until Flutter is updated and you rebuild the app. Sure, most of the non-tech users would not even notice this, and would not care, if the app looks good enough - not necessarily 100% consistent and smooth as a native iOS app. 
c) Be careful if you plan to use Flutter for one or two sections of the existing app. The difference between native look and feel of the app and cross-platform build is more noticeable in this case and can be a deal-breaker if your client is a purist. 
d) Let’s take that you and your users don’t care too much about the native look of the app, and your priority is to save time. Then why not just to take MaterialApp and compile it both for Android and iOS? Yes, your app will have a non-native appearance, but it will work fine.  And vise versa - if you do care about the look and feel - you’ll have to use CupertinoApp and MaterialApp, as well as duplicate most of the code for UI, which often is a big part of the app, and makes the architecture more complex. So think twice about the future of the application before choosing the approach.

  1. Due to the size of the community and relative youth of the technology, Flutter’s list of plugins is much shorter than React Native or Xamarin have.  So far the choice is limited, some plugins exist only for one platform, some are not maintained, and may not work with current Flutter/Dart version. As far as Flutter comes from Google, Android developers are much more into it than iOS developers, so it’s a common cause to have some plugin supported for Android, and it comes up to fill the missing pieces of the code for iOS. But still, it’s better than writing from scratch. We hope that in the near future this will change with the growing popularity of the technology. 
  2. Debug process is similar to what you have in Java, Kotlin Android - you can use breakpoint, go step by step through the code and inspect variable values. Works both for Android studio and VSCode. Still, the overall method is quite different comparing to native SDK’s and takes some time to get used to it.  When you get a layout error, the error screen/log look confusing because it points out to the line of code, which can be many levels of abstractions below the line you directly interact with. In native SDK the errors are usually easier to work with, at least because just copy and paste the whole error to Google gives you valuable links where you can read more. Due to the small size of a Flutter community, googling works not that good so far.
  3.   An easy and direct approach to UI creating - you keep it in the same .dart files where the code for the screen is. Again - not that usual experience, especially if you are used creating UI code with a markup code, and keeping it in separate files.
  4.  No architectural pattern (so far).  For Android and iOS, the majority of developers are used to some architectural patterns (Clean Architecture, MVC, MVP, MVVM) that proved themselves to work well for big-size apps. from this point of view - Flutter does not have any unified architectural pattern. That means if you plan to use Flutter for a large project - you must aim past the horizon and have a clear vision of how the app will be structured. Complexity always grows, so think in advance about scalability, maintainability and comprehensible architecture. Also, this means additional working hours spent, as some of the first architectural decisions may be changed soon. 
Flutter has a lot of potentials, and currently is one of the most simple technologies to switch to. Probably, that’s the fastest technology to create something real fast, though there are some new ideas and approaches under the hood. The only issue here is the networking effect - the community of Flutter is not that big so far, which means that in terms of cross-platform plugins a lot of things is still missing. And yes, you should be OK with the fact, that your UI will not have 100% native look, otherwise be ready to spend more time on reworking the app structure.
However, for some particular cases flutter is one of the best options.

  1. If you are a startup and your goal id a super-fast release and outreach of as many people as you can, so you need a product working on both platforms. It’s possible to build a very advanced prototype within a month or two, which can be further polished later still staying on Flutter or replaced by a native version depending on the user’s feedback.
  2. If you use Flutter for software where UI is not a priority, like Enterprise/B2B apps, where you want to have a line-of-business app that employees/customers can use with any type of device, but aren’t too concerned about it being consistent with everything else in the OS ecosystem.