The original link

Basic knowledge of Flutter Caton optimization

First of all, we need to understand the basics of Flutter before we do performance tuning, otherwise we won’t be able to start. First, we need to understand what Flutter is all about –Flutter is a cross-platform mobile UI framework released by Google in 2018.

However, it is efficient compared to other cross-platform frameworks, and the reasons why it is efficient are as follows:

He calls the Skia framework directly, while the other frameworks need to use the existing original framework to rotate. Before he starts to call the Skia framework, this one and the other must consume something. This is one of them.

Four threads

Respectively is:

Platform thread

The main thread of the platform. This is where the plug-in code runs. See the UIKit documentation for iOS or the MainThread documentation for Android for more information. The performance layer does not show the thread.

DartUI thread

The UI thread executes the Dart code in the Dart VM. This thread includes code written by the developer and code generated by the Flutter framework based on application behavior. When an application creates and displays a scene, the UI thread first creates a Layer Tree, a lightweight object that contains device-independent render commands, and sends the layer tree to the GPU thread to render on the device. Do not block this thread! Display the thread in the lowest bar of the performance layer.

GPU thread

The GPU thread retrieves the layer tree and tells the GPU to render. Although there is no way to communicate directly with the GPU thread or its data, if that thread is slow, it must be caused somewhere in the developer’s Dart code. The graphics library Skia runs on this thread, sometimes called a rasterizer thread. Displays the thread in the top bar of the performance layer.

I/O thread

It may block time-consuming tasks (mostly I/O) in the UI or GPU thread. This thread is not shown in the performance layer.

So, when we do performance optimizations, we care about DartUI, we care about the GPU thread, we care about frames, we care about the GPU thread, these two are the key, and 99% of the time, as Flutter developers, we have basically solved the DartUI thread problem, and we have solved the rendering performance problem.

The three trees

  • Widgets describe the configuration required for an Element, create it, and determine whether it needs to be updated. The Flutter Framework uses a difference algorithm to determine whether the Element’s State changes by comparing changes in the Widget tree. If nothing has changed since rebuilding the Widget tree, Element does not trigger a redraw, so rebuilding the Widget tree does not necessarily trigger rebuilding the Element tree.
  • Element represents an instance of a Widget at a specific location in the Widget configuration tree, holds both the Widget and RenderObject, and is responsible for managing Widget configuration and RenderObject rendering. The Element state is managed by the Flutter Framework and the developer only needs to change the Widget.
  • RenderObject represents an object in the rendering tree that does the real rendering work, such as measuring size, position, and drawing.

In order to visualize the three trees from birth to death, I have to throw out the following picture

Then, we often use the Timeline tool for performance tuning, and you’ll see a picture like this:

We have 4 threads, build-layout, paint, and so on, and we can see where they are, what they are, and who comes first.

Therefore, to solve the problem of frame lag, we need to solve the three stages of build,layout,paint function execution time problem.

How to optimize performance

First of all, we configuration environment, here I configure the variable debugProfileBuildsEnabled = true, otherwise I don’t know the build what had he done the specific what, watch the default won’t tell me. In general, place it in the main function and open it before runApp. For example, here’s what I did:

There are some other switches that need to be used, which can be turned on when the data is insufficient, so that we can refer to more data and optimize the reference point more clearly.

Then, we execute flutter Run –profile. Remember, we need to tune performance in Profile mode, debug mode, because a lot of analysis data is recorded during rendering and the feature that supports hot overloading costs a lot of performance. Profile mode is much closer to release mode performance.

Then it runs, and a link appears:

Click on it and go to the platform. Of course, you can also use devTools, which seems to replace the platform later. The devTools startup position is:

flutter pub global activate devtools
devToolsCopy the code

Install first, and then run in direct:

Click on this link, and a page will pop up asking you to type in the URL, and that URL is the URL of our observatory, so you seem to get it. However, devTools is an analysis tool built on the foundation of the Observatory, so Google must think the Observatory is not very friendly. Unfortunately, DevTools is not very comprehensive because it’s still preview and everything will be fine.

If there is a performance problem with our app, we will open the window, open The timeLine, click Flutter Develop, and make a note of the page that you think has a problem with Flutter. Then click Refresh in the upper right corner. This will appear:

In general, it’s very easy to find the problem areas, obviously the ones that are wide and the ones that are long, and that sort of takes the time to figure out that the page is loading slowly, and then we click on the down arrow to zoom in a little bit

Then, we click Select and select a range to see the statistical effect:

At this point, we see the problem, and then this also loads so many TipcachenetWorkImages, and then it takes about 2ms each, and then I have a list page:

So, there are 8 such controls to render, and he takes up 8 *2.188 > 16ms, so we found the optimization point, solve this can speed up the rendering, here is just an example to find the performance bottleneck, specific related function time optimization, I believe we all understand, this is the algorithm related problem.

Then there are some code suggestions

1. Try to put setState on the leaf node, the advantage is that the influence range during build is very small, referred to as local refresh

2. Do not use any Opacity Widget if possible, because it will send a saveLayer command to the GPU, which is time-consuming, according to Skia.

3. Use listView.Builder () instead of using ListView() directly to build lists.

4. For frequently updated controls (e.g. countdown, stopwatch) use RepaintBoundary to isolate it in a separate paint area.

5. Use const to decorate controls that never need to be changed.

Use statelessWidgets in preference to all statefulWidgets

7, use the Visibility control to replace if/else, some small partners like else return a placeholder control, you must not know, this efficiency is not efficient Visibility.

The resources

Debug the Flutter application – Flutter Chinese Documentation – Flutter Community Chinese resources

zhuanlan.zhihu.com/p/88478737

Files. The flutter – IO. Cn/events/gdd2…

Best Practices for Optimizing the Performance of Flutter applications – Flutter Documentation – Flutter Community Resources

mrale.ph/dartvm/

Medium.com/flutter/man…