One, foreword

The article on Flutter dynamics has not been updated for a long time. The development of this part was mainly an experimental exploration outside the normal work of the company, which used scattered time to reconstruct and optimize one by one. Up to now, a relatively complete version has been completed, and a small piece of business function of the company’s App has been put online for trial in a small range.

The principle and thinking of Flutter dynamic can be referred to previous articles. After optimization practice in this period of time, the current dynamic implementation process of Flutter is summarized as follows:

Runtime execution is as follows:

The Runtime Parser Parser mainly parses the Ast syntax tree and executes corresponding syntax functions. It consists of two parts:

  1. Basic syntax parser
  2. Extended parser

See figure below:

// The parser interface, //* target({int a, String b}) //* target({int a, String b}) //* target. Property (int a, String b) String b) ///* target.property({int a, String b}) ///* target.property dynamic parse( AstRuntime runtime, dynamic target, { String property, List<Expression> arguments, });Copy the code

Parser is basically a physical strength live, enumeration most common grammar and common base class, and at the same time provides an extension of the parser interface, if need to parse the custom objects (such as custom UI components or tools, etc.), and implement this interface can be added to the parser, follow the requirements need to be continually iterative complement the parser.

Second, business scene actual combat

The business function we are going to practice is a message list interface that looks like this:

The elements of the interface are not complex, and it is also a common list interface. After dynamic processing of this interface, the operation effect is as follows:

You can obviously see that the lag is very serious when rolling and the experience is very bad

1. Problem analysis

Open DevTool analysis:

Generally, the frame number for human eyes to recognize coherent actions is 24fps, so the length of a frame should not exceed 40ms. Usually, the frame number we feel comfortable is 60FPS, which is also the standard commonly used at present, so the length of a frame should be controlled within 15ms. As can be seen from the above figure, when this list is scrolling, the time of a frame has reached 560.4ms, and the feeling of lag is very strong in the sliding process. The reason for the problem can also be clearly seen in DevTool, is in the parser part, recursively called a lot of times, the screenshot is not complete, there are actually a lot of calls below, I have not thought of a good way to optimize this part, can only use this relatively rough method to parse each node in the Ast tree.

2. Solution

Analytic algorithm optimization is not an option for the time being. , which warrior can show you how to “hold fists”), there are several optimization directions left:

  1. Execute the parser in the child thread
  2. The parser part is implemented in a more efficient language, such as C/C++
  3. Use idle CPU time to manually control the rendering timing

Make feasibility analysis on these directions:

First of all, after investigation, the first method is not suitable for Flutter. We know that the thread of Flutter is called ISOLATE, and that THE ISOLATE does not support shared memory. Multiple ISOLates communicate with each other through ports provided internally. The communication data types can only be the basic data type and the internal SendPort object. If you want to transfer other class objects, unless serialized to the basic data type for transmission. One of the problems is that the widgets cannot be processed. The widgets parsed in the child ISOLATE cannot be transmitted to the parent isolate. The widgets themselves are complex and do not provide serialization, so the first solution is passed.

The second option has the same problem: how do you build Widget objects in C/C++? How have built objects been transferred to the Flutter layer?

The remaining feasible scheme is the third one, which is the same as the common list scrolling optimization method at present. It is not parsed when sliding, and the parser task is executed during the interactive idle period at the end of sliding.

3. Realization of the third scheme

The implementation process is as follows:

The principle of the Flutter SDK is not complicated. What is more important is how to obtain the index interval of the displayed list items. There is no relevant method in the Flutter SDK, but the Package of a third party is used: Scrollable_positioned_list, also produced by Google, interested in children’s shoes can see the source code implementation.

The final optimization effect:

This solution is not perfect. Although the sliding experience is much better than before, the waiting time for loading list items is still quite long. If you have other optimization ideas, please discuss them in the comments section