I am Guo Shuyu, the author of “Detailed Description of Flutter Development” and the leader of Github GSY open source project. The open source GSY_Github_app_FLUTTER currently ranks first in the DART rankings with a star of 13K +.

Data source: github.com/GrowingGit/…

Prior to the start

Flutter has been open source for nearly 7 years now, and I started to learn about Flutter in 2017. In 2022, Flutter is no longer a niche cross-platform framework.

As shown in the figure, we can see that Flutter now has a star of 135K. 10K + Open and 50K + Closed issues are sufficient to indicate the activity of Flutter community and users.

Flutter was also the number one used and loved cross-platform framework in the second half of last year. This is not to say that you have to learn Flutter, but rather that Flutter has proved its worth whether we like it or not.

Data source: rvtechnologies.com/10-reasons-…

In fact, last year and the year before, I did some simple statistics:

  • In 2020,52It’s in one sample19Flutter appeared in one App;
  • In 2021,46It’s in one sample24Flutter appeared in one App;

This data sample is relatively small. It is mainly collected from my frequently used App, so it is not accurate or representative. However, it can reflect the current situation of Flutter application in China to a certain extent.

Data source: juejin.cn/post/701238…

Finally, Flutter is also supported on the Web and PC, but I have not put it into production yet. I can summarize this briefly:

Web

  • Flutter Web is currently supportedHtmlCanvasCanvasKit(WASM), the default is to use HTML on mobile and WASM on desktop;
  • Pub. Dev60%The left and right packages are Web compatible;
  • Volume and SEO are the most important issues to consider in advance;

Reference: juejin.cn/post/705961…

Desktop

PC is relatively weak at present. If compared with Electron, it can be simply said that Flutter PC can use a lower memory footprint, a smaller size, and even better FFI ability to inherit FROM C. However, the same ecology is also weaker and there is relatively less third-party support. There will be more problems that need to be solved independently.

The Window production version has been officially released

Reference: juejin.cn/post/701845…

Flutter differs from native development

The main feature of Flutter as a cross-platform UI framework is that the framework’s UI is platform-independent, as long as its performance is good. From the platform’s point of view, Flutter is a “single-page” application.

1. Single-page apps

What is a “single page” application?

For native Android and iOS, the entire cross-platform UI runs on an Activity/ViewController by default. By default, there is only one Activity/ViewController. In fact, Flutter, ReactNative, Weex, and Ionic all do this by default, so there is no direct relationship between frame routing and native routing.

For example, as you can see in the picture below,

  • There is in the current route stack at the Flutter endFlutterAFlutterBTwo pages Flutter pages;
  • Open a new oneActivity / ViewController, launched theNative page XAs you can seeNative page XAfter being added as a new native page to the native layer routing, theFlutterActivity / FlutterViewControllerTo block, that means to putFlutterAFlutterBBlocking;
  • Then open new ones in the Flutter layerFlutterCPage, as you can see, will still be blocked by the native page X;

As you can see from this section, cross-platform applications are by default single-page applications, and their routing stack is incompatibly isolated from the native layer.

There is, of course, a word repeated: The “default”, which actually supports custom mixed stacks, such as the official FlutterEngineGroup, third-party frameworks such as Flutter_boost, mix_stack, Flutter_thrio, etc. are all designed to address mixed development scenarios.

2. Rendering logic

After explaining the differences in the “single page” section, let’s talk about how Flutter is different at the render level.

There is a big difference between Flutter and other cross-platform frameworks at the rendering level. Here is a comparison of common rendering modes at this stage:

  • For native Android, it is the native code after SKia to GPU rendering, Android native system itself has SKia;

  • For Flutter, the Dart code controls pass through the SKIA to be rendered on a GPU. The SkIA used on Android and the SKIA packaged into the project are used on iOS.

  • For ReactNative/Weex and similar projects, they are running in their respective JS engines, and finally through mapping to native controls, using native rendering capabilities for rendering; (PS, the official refactoring will finally be released this year: a new architecture update for React Native in 2022)

  • For Hybird’s cross-platform frameworks such as ionic, the main use is WebView’s rendering capabilities;

Skia on Android can be OpenGL or Vulkan depending on the situation, and on iOS will use Metal to speed up rendering if there is Metal support.

From the previous introduction, it can be seen that:

Cross-platform and native platforms like ReactNative/Weex have a lot of relevance:

  • The advantage is that if you need to use the control capabilities of the native platform, the access cost is lower.

  • Disadvantages of nature is: rendering heavily depends on the ability of platform controls, more coupling, differences between native controls between different systems, different versions of the same system in the control of the property and effect differences, combined in the later development process is a great maintenance cost.

For example, a debugged style on iOS fails on Android. Styles that work on Android are not supported on iOS; Control effect in iOS platform, in Android has a different display, such as drop-down refresh, Appbar, etc.; When these issues are combined with the nuances of the Framework for each system version, they can become daunting.

Another example is the shadow effect difference between Android and iOS.

Flutter differs from this by rendering directly using SKIA and GPU interaction, implementing platform-independent controls on both Android and iOS platforms. In short, most of the widgets in Flutter are not related to Android or iOS.

Essentially native platforms are provided with a similarSurfaceAll that is left is for Flutter to render the corresponding controls

FlutterView is generally used as the rendering host. It can be used internally on Android as SurfaceView, TextureView or FlutterImageView. On iOS it’s UIView rendering through Layer.

Therefore, Flutter controls have the same effect on different platforms. However, mixing with native controls can be costly and difficult. In addition to the ability to access native controls, Flutter provides a PlatformView mechanism for access. PlatformView’s implementation is more prone to memory and keyboard issues, which can lead to higher access costs.

The current version basically requires Hybrid Composition, so it’s a little bit better than PlatformView, but there are still some issues. For example, password keyboard switching, page switching when PlatformView page flashing.

3. Project structure

As shown in the figure above, the default Flutter engineering structure looks like this:

  • androidNative project directory, can be configured nativeappNamelogo, startup diagram,AndroidManifestAnd so on;
  • iosProject directory, configuration startup diagram,logo, application name,plistDocuments and so on;
  • buildGit’s ignore directory, where the packaging process and input results are stored. The native Android packaging process output is also redirected to this directory.
  • libDirectory, used to write the Dart code, the entry file is usuallymain.dart;
  • pubspec.yamlFiles, one of the most important files in the Flutter project, are written here, whether static resource references (images, fonts), third-party library dependencies, or Dart release statements.

The following figure shows the structure of the pubspec.yaml file

Note that when the file changes, you need to re-execute the flutter pub get and restart the project after stopping the application instead of using hotload.

The following is the Plugin project for Flutter. Flutter is divided into Package and Plugin

  • PackageThe project belongs to the Flutter package project and will not contain native code.
  • PluginThis project belongs to the Flutter plugin project, including Android and iOS code;

4. Package debugging

Before a Flutter can run, you need to execute a Flutter pub get to download third-party code simultaneously. The downloaded third-party code usually exists in (Mac) /Users/ your username /.pub-cache.

Once the dependencies have been downloaded, you can start the Flutter project directly using the Flutter Run or IDE tool by clicking run. This process requires some network synchronization of the native project, such as:

  • Gradle and AAR dependencies on Android are synchronized.
  • Pod Install is required to synchronize some dependencies on iOS.

If you need to view progress during project synchronization:

  • Android can go to theandroid/Directory execution./gradlew assembleDebugView the synchronization progress.
  • IOS can go to theios/Directory executionpod install, view the download progress;

If the Plugin has native platform code logic, you can see.flutter_plugins and.flutter_plugins in the root directory of the project. This file is used by Android and iOS to reference plug-ins to the local path, and then dynamically add dependencies to this path when Flutter runs.

By default, Flutter runs in JIT mode with DEBUG, so it is inefficient and relatively slow, but can be hotloaded.

The release mode is AOT mode, which will run much faster. Also, Flutter will run by default on the emulator using CPU, while Flutter will run on the real machine using GPU, so its performance is different.

In addition, iOS 14 real machine debug runs, after the link is broken and restarted again cannot run.

If a project has cache problems, flutter Clean can be directly executed to clean the cache.

Finally, why doesn’t Flutter support thermal updates?

As mentioned before, ReactNative and Weex render by converting the controls in JS code into native controls, so JS code parts are just text in essence. Using code-push to push text content does not violate the requirements of the platform in essence.

The files that Flutter packages are binary files. Pushing binary files is obviously not suitable for the platform.

Release will generate two dynamic libraries, app.so and flutter. IOS generates App. Framework and Flutter. Framework files.

So the common third-party thermal updates for Flutter on the market are: MxFlutter, Fair, Kraken, liteApp, NEJFlutter, Flap (MTFlutter), Flutter_code_push (Chimera), etc. None of these frameworks will deliver executable binaries directly. Depending on DSLS, dynamic solutions fall into two broad categories: front-end oriented and terminal oriented.

WXG’s LiteApp, Tencent’s MxFlutter and Ali’s Kraken (Beihai), for example, are front-end oriented and use JS/TS, as shown below.

Resources: mp.weixin.qq.com/s/OpgqjTIiB…

As shown in the figure below, Flap and Flutter_CODE_PUSH are terminal oriented, focusing on Dart DSL or coding.

Resources: tech.meituan.com/2020/06/23/…

Finally, for the support of dynamic Flutter thermal renewal, please refer to this table:

Reference: Flutter dynamic update – Technical prestudy juejin.cn/post/703370…

5. A brief introduction to Flutter

Here is a section on the Flutter Dart. For native development, Flutter is primarily responsive and Widget oriented.

responsive

Responsive programming, also known as declarative programming, is now the mainstream of front-end development, and certainly a trend for client development, such as Jetpack Compose and SwiftUI.

Jetpack Compose and Flutter look very similar in some ways.

Responsiveness simply means that you don’t need to manually update the interface, you just need to “declare” the interface through code, and then connect the relationship between the data and the interface, and the interface will be updated as the data is updated.

From the code side, for native development, there is no XML layout, no storyboard, layout is all done by code, what you see is what you get, and there is no interface “object” to assign and update, all you need to do is configure the relationship between the data and the interface.

Reactive development differs from data binding or MVVM in that it reconstructs and adjusts the entire render tree each time, rather than simply visibility the UI.

The following figure shows a typical third-party example of a responsive UI under Flutter: responsive_framework

Widget

Widgets are the fundamental concept of a Flutter and the object with which we write code most directly. Everything in a Flutter is a Widget. Widgets are immutable, and each Widget state represents a frame.

Therefore, as an IMmutable object, widgets cannot be real working UI objects. The real view-level objects in Flutter are Element and RenderObject. Element’s abstract object is the BuildContext we use a lot.

For example, as shown in the following code, testUseAll Text is used in three places on the same page, and the code renders normally. If it is a real View, it cannot be used in multiple places on the same page.

Therefore, Flutter widgets are more of a configuration file that describes the configuration code of the interface. For details about their implementation logic, relationship, and classification, see chapter 3 and chapter 4 of my book “Flutter Development in Action”.

Interesting question

Finally, a more interesting question. Someone said that Flutter is a transfer of value or a reference? There are many articles on the Internet that give strange and misleading explanations to this question. In fact, the question is very simple:

Everything in Flutter is an object, evenintdoubleboolIt’s also an object. What do you think an object passes?

Operator operator operator operator operator operator operator operator operator operator operator operator operator operator operator operator operator operator operator operator operator operator

For this operation, just go to the Dart VM and see what happens when the Double object is added, subtracted, multiplied and divided, as shown in the figure below.

Flutter and Compose

Finally, Flutter and Compose.

In fact, since Jetpack Compose came out, the choice between Flutter and swarm has been a problem in Android development, just like iOSer’s decision to choose between Flutter and SwiftUI. One of the more troubling aspects of Android development is that Flutter and Swarm are the same parent.

I am only offering my personal understanding here and do not represent an official view:

Flutter and Compose have the same future goals, but at least they have different origins.

Compose is the new UI library for the Jetpack family. Understand that! Compose is a member of the Jetpack family, so it can be used for Android UI development, so you can either use it or not.

Compose was born to redefine the way UI writing is done on Android, to improve the efficiency of Android’s native UI development, and to bring Android UI development up to date.

Like it or not, declarative interface development is the way of the day, as shown by React, SwiftUI, Flutter, etc.

For Flutter, it is cross-platform, because Flutter has no platform of its own. Some people say that Fuchsia will be the home of Flutter. But that is a future story, because Fuchsia needs to feed itself first.

Since Flutter was born as a new UI framework designed to exist across platforms, from bottom to top it is an “innovative” and “bold” design. Choosing Dart itself is a “bold” decision, even supporting Canvaskit’s WASM mode on the Web platform.

Therefore, the “willfulness” of Flutter was not viewed favorably from the beginning. Of course, there are still people who do not view Flutter favorably, because Flutter is somewhat “extreme” and unfriendly.

In addition, from the origin and maintenance:

  • Flutter origin is the Chrome project team, which chose Dart, so Flutter is not an Android project;
  • Compose originated with the Android team and uses Kotlin;

Therefore, their origin and maintenance belong to different groups, so we may think there is resource conflict from the outside world, but in essence, they are maintained by different large groups.

All right, so with that said, here’s the summary:

  • Compose is the future of the Android UI. For now, you may not, but if you’re going to be on The Android platform in the future, you’ll have to. , and Compose is moving forward with cross-platform support, not maintained by Google, but the Compose for Compose Multiplatform provided by Jetpack.

  • The future of Flutter is multi-platform, a more stable and reliable multi-platform UI framework. If you’re not going to be a big front-end or multi-end developer, it doesn’t matter if you can’t.

However, it may be more important to decide which one your boss requires you to use. Come back to the conflict of Flutter and Compose?

Flutter and Compose seem to conflict in the sense of project establishment, but they do not conflict from the user’s point of view.

Because for developers, whether you learn Compose or Flutter first, it will help you to master the other skill. Learning one is equivalent to learning 70% of the other skill

From the perspective of the future:

  • If you are a native developer and have not yet been exposed to Flutter, learn Swarm first, which will be more helpful for your Android career, and then learn Flutter.

  • If you are already using or learning about Flutter, please continue your education and do not have to worry about Compose. You will not be too far away from Flutter once you master Flutter.

Both of them are going to be multi-platform in the future, and I think the conflict is more about hands-on learning, rather than being torn between the two.

From a practical point of view: Android and iOS are Stable under Flutter 2.0. The Web has entered the Stable branch, and Macos/Linux/Win has entered the Beta stage. It can be previewed with snapshot in the Stable branch. So from this stage, if you need to develop cross-platform, even on PC, then Flutter should be a priority.

React Native isn’t a bad choice. The React Native version is now 0.67, but still not 1.0

The question is whether you accept these potholes. Behind the platform itself is “dirty work” and “tiring work”. The whole path of Flutter is difficult. Getting good Android and iOS support and compatibility is not easy.

One last thing to add routinely:

The reason why cross-platform is cross-platform, first of all, is the existence of the corresponding native platform. Many problems of the native platform need to be solved by the platform. Those who like to talk about XXX and dominate the native and cool rhythm, just because “your anxiety will become their profit”.