In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article is to share with you about what flutter is. The editor thinks it is very practical, so share it with you as a reference and follow the editor to have a look.
Flutter architecture
Image
The Flutter framework consists of three layers
Framework,Engine, Embedder
Framework is implemented in Dart language, including UI, text, pictures, buttons and other Widgets, rendering, animation, gestures and so on. The core code of this part is flutter package under flutter warehouse, and package under sky_engine warehouse such as io, async, ui (dart:ui library provides the interface between Flutter framework and engine).
Engine is implemented using C++, which mainly includes Skia, Dart and Text.
Skia is an open source two-dimensional graphics library, which provides a general API for a variety of software and hardware platforms. It has been used as the graphics engine of Google Chrome,Chrome OS,Android, Mozilla Firefox, Firefox OS and many other products, and the supporting platforms include Windows, macOS, iOS,Android,Ubuntu and so on.
The Dart section mainly includes: Dart Runtime,Garbage Collection (GC) and, if it is Debug mode, JIT (Just In Time) support. In Release and Profile mode, it is AOT (Ahead Of Time) that compiles into native arm code, and there is no JIT part.
Text is text rendering, which is rendered at the following levels: derived from Minikin's libtxt library (for font selection, delimiting lines); HartBuzz for glyph selection and shaping; and Skia as the rendering / GPU backend, rendering using FreeType on Android and Fuchsia, and rendering fonts using CoreGraphics on iOS.
Embedder is an embedded layer through which Flutter is embedded on various platforms. The main work of Embedder includes rendering Surface settings, thread settings, and plug-ins. Platforms such as iOS just provide a canvas, and all the rest of the rendering-related logic is within Flutter, which makes it cross-end consistent.
Dart language
Dart is also a VM language, so there is a dart runtime in every app that runs flutter. The compilation mode supports AOT and JIT.
Dart was originally designed by google to replace javascript, but it didn't work. Later, Flutter chose Dart to make Dart active.
Features of the Dart language:
Single process asynchronous event model
Strongly typed, can be inferred by type
VM with extremely high running efficiency and excellent code running optimization, according to earlier benchmarks, performance is comparable to Java7's JVM
Unique quarantine zone (Isolate), which can implement multithreading
Object-oriented programming, all data types are derived from Object
Operator overloading, generic support
Powerful Future and Stream models that can easily implement efficient code
Minix feature, which can better realize method reuse
Full-platform language, can be very competent for mobile and front-end development
Syntactically, Dart provides a lot of convenient operations
Flutter thread management
Flutter Engine does not create its own, but manages threads. Embedder is responsible for the creation and management of Flutter Engine threads.
Embeder provides four Task Runner, each of which is responsible for different tasks. Flutter Engine doesn't care which thread Task Runner runs on, but it requires thread configuration to be stable throughout the life cycle. In other words, it is best to keep a Runner running on the same thread all the time.
Platform Task Runner
Is the main Task Runner of Flutter Engine, and the thread running Platform Task Runner can be understood as the main thread. Similar to the Main Thread of Android Main Thread or iOS. For Flutter Engine, the thread on which Platform Runner resides is not substantially different from other threads. Multiple Engine instances can be started at the same time, with each Engine corresponding to a Platform Runner, and each Runner running in its own thread. This is how Content Handler works in Fuchsia (the operating engine that Google is developing). In general, when a Flutter application starts, it creates an instance of Engine, and when Engine is created, it creates a thread for Platform Runner to use.
All interactions with Flutter Engine (interface calls) must take place in Platform Thread, and an attempt to call Flutter Engine in another thread will result in an unexpected exception. This is similar to what both Android and IOS have to do with UI on the main thread. It is important to note that there are many modules in Flutter Engine that are not thread safe. Once the engine is up and running, all engine API calls will occur in Platform Thread.
The Thread where Platform Runner resides not only handles interactions with Engine, it also handles messages from the platform. This kind of processing is more convenient, because almost all engine calls can only be safe in Platform Thread, and Native Plugins does not need to do additional threading operations to ensure that operations can be done in Platform Thread. If Plugin starts an extra thread on its own, it is responsible for sending the return result back to Platform Thread so that Dart can handle it safely. The rule is simple: all interface calls to Flutter Engine need to be made in Platform Thread.
Blocking Platform Thread does not directly cause stutters in Flutter applications (different from the iOS android main thread). However, the platform still has enforcement restrictions on Platform Thread. Therefore, it is recommended that complex computing logic operations be placed not on Platform Thread but on other threads (excluding the four threads we are talking about now). When the other threads finish processing, forward the results back to Platform Thread. If the Platform Thread application is stuck for a long time, it may be forcibly killed by the system Watchdot.
UI Task Runner
Flutter Engine is used to execute Dart root isolate code. Root isolate is special in that it binds a lot of function methods needed by Flutter. Root isolate runs the main code of the application. When the engine starts, it adds the necessary binding to make it have the ability to schedule and submit rendered frames.
For each frame, the engine does the following:
Root isolate informs Flutter Engine that there are frames to render.
Flutter Engine notifies the platform and needs to be notified at the next vsync.
The platform waits for the next vsync
Layout the created object and Widgets and generate a Layer Tree,Layer Tree that is immediately submitted to Flutter Engine. There is no rasterization at this stage, and this step simply generates a description of what needs to be drawn.
Create or update a Tree that contains semantic information for displaying Widgets on the screen. This thing is mainly used for the configuration and rendering of platform-related auxiliary Accessibility elements.
In addition to rendering related logic, Root Isolate also handles message responses from Native Plugins, Timers,MicroTasks and asynchronous IO.
Root Isolate is responsible for creating the managed Layer Tree and ultimately decides what to draw to the screen. Therefore, the overload of this thread will directly cause the stutter to drop the frame.
If there is an unavoidable heavy computation, it is recommended to perform it in a separate Isolate, such as using the compute keyword or non-Root Isolate, so as to avoid the application of UI stutters. But it should be noted that non-Root Isolate lacks some of the function bindings required by the Flutter engine, and you cannot interact directly with Flutter Engine in this Isolate. So independent Isolate is used only when a large number of calculations are needed.
GPU Task Runner
Used to perform related calls to the device GPU. The Layer Tree information created by UI Task Runner is platform-independent, that is to say, Layer Tree provides the information needed for rendering, and how to implement rendering depends on the specific platform and method, which can be OpenGL,Vulkan, software rendering or other drawing implementation of Skia configuration. The modules in GPU Task Runner are responsible for translating the information provided by Layer Tree into actual GPU instructions. GPU Task Runner is also responsible for configuring and managing the GPU resources needed for each frame rendering, including the creation of the platform Framebuffer, Surface life cycle management, to ensure that Texture and Buffers are available when drawing.
Based on the processing time of Layer Tree and the time it takes for GPU frames to be displayed to the screen, GPU Task Runner may delay the scheduling of the next frame in UI Task Runner. Generally speaking, UI Runner and GPU Runner run on different threads. It is possible that while UI Runner is ready for the next frame, GPU Runner is still submitting the previous frame to GPU. This delayed scheduling mechanism ensures that UI Runner does not assign too many tasks to GPU Runner.
GPU Runner can cause the delay of frame scheduling of UI Runner, and the overload of GPU Runner will lead to stutter of Flutter application. Generally speaking, users do not have the opportunity to submit tasks directly to GPU Runner because neither the platform nor Dart code can run into GPU Runner. But Embeder can still submit tasks to GPU Runner. Therefore, it is recommended to create a new dedicated GPU Runner thread for each Engine instance.
IO Task Runner
The main function is to read the compressed image format from the image storage (such as disk) and process the image data to prepare for GPU Runner rendering. In the preparation of Texture, IO Runner first reads the compressed image binary data (such as PNG,JPEG), decompresses it and converts it into a format that GPU can handle, and then uploads the data to GPU. These complex operations can lead to Flutter application UI stutters if they run on the GPU thread. But only GPU Runner can access GPU, so the IO Runner module is configured with a special Context when the engine starts, which is in the same ShareGroup as the Context used by GPU Runner. In fact, the reading and decompression of image data can be done in a thread pool, but the access to this Context can only be guaranteed in specific threads. This is why you need a special Runner to handle IO tasks. The only way to get resources such as ui.Image is through async call, and when this call occurs, Flutter Framework tells IO Runner to perform the image asynchronous operations just mentioned. In this way, GPU Runner can use the image data prepared by IO Runner without additional operations.
User operations, whether Dart Code or Native Plugins, have no way to access IO Runner directly. Although Embeder can schedule some generally complex tasks to IO Runner, which does not directly lead to stutters in Flutter applications, it may cause delays in loading pictures and other resources to indirectly affect performance. Therefore, it is recommended to create a dedicated thread for IO Runner
Each Engine instance on the android & iOS platform creates a new thread for UI,GPU,IO Runner when it starts. All Engine instances share the same Platform Runner thread
Isolate
Image
An isolated Dart execution context
Isolate is Dart's implementation of actor concurrency mode. The running Dart program consists of one or more actor, and actor is the isolate in the concept of Dart. Isolate is isolated, and each isolate has its own memory and single-threaded entity. Isolate does not share memory with each other, and it is independent of GC.
The code in isolate is executed sequentially and is single-threaded, so there is no problem of resource contention and variable state synchronization, so locks are not needed. Concurrency in Dart is implemented in parallel by multiple isolate.
Because isolate does not share memory, isolate can not communicate directly with each other, only through Port, and it is asynchronous
Flutter Engine Runners and Dart Isolate
Dart's Isolate is managed by the Dart virtual machine itself, and Flutter Engine cannot directly access it. Root Isolate submits UI rendering related tasks to UI Runner for execution through Dart's C++ call ability, so that it can interact with Flutter Engine related modules. Flutter UI related tasks are also submitted to UI Runner and can also give Isolate some event notifications accordingly. UI Runner also handles tasks from App Native Plugin. Dart isolate and Flutter Runner are independent of each other, and they cooperate with each other through task scheduling mechanism.
Dart memory management
Dart VM divides memory management into the new generation (New Generation) and the old age (Old Generation)
Cenozoic: the objects allocated for the first time are in the Cenozoic era, and this area mainly stores objects with small memory and short life cycle, such as local variables. The new generation will frequently perform memory collection (GC), which uses the copy-clear algorithm to divide the memory into two chunks, one of which is used at a time and the other is reserved at a time. When GC occurs, copy the surviving objects in the currently used memory block to the spare memory block, then clear the currently used memory block, and finally, swap the roles of the two blocks of memory.
Old age: objects that "survive" in the new generation of GC will be transferred to the old age. In the old days, objects with longer life cycle and larger memory were stored. In the old era, GC recycling uses the "mark-clear" algorithm, which is divided into two stages: marking and clearing. In the marking phase, a pause will be triggered, and multi-threads concurrently complete the marking of junk objects, reducing the time-consuming of the marking phase. In the cleaning phase, the GC thread is responsible for cleaning up the recycled objects and executes at the same time as the application thread, which does not affect the running of the application.
Memory occupied by image in Flutter
Android divides the medium memory into java memory or native memory, and usually the requested memory in the code falls within these two ranges.
Java memory refers to memory objects allocated by java or kotlin
Native memory refers to the memory allocated by CCompact +, and also includes the memory occupied by some native android systems, such as image resources and other graphics.
Image in Flutter does not use these two kinds of memory, but Graphics memory. Graphics memory refers to the memory used by the graphics buffer queue to display pixels to the screen, and the graphics buffer refers to the GL surface, GL texture and so on. Graphics memory is memory shared with CPU, not GPU-specific memory
Flutter operation mode
Common operating modes of Flutter: Debug,Release and Profile
The Release pattern is similar to the Profile pattern, except that it supports service extensions for the Profile pattern, supports tracing, and minimizes the dependencies required to use trace information. Profile does not support simulators because diagnostics on simulators do not represent real performance. All key points are introduced.
The difference between Debug and Release
Debug mode: compiled using JIT, supporting simulators and devices. Assertion support is turned on, including all debugging information, service extensions and debugging aids such as Observatory. This pattern is optimized for rapid development and operation, but not for execution speed, package size, and deployment.
So it can achieve second-level hot reload.
Release mode: compiled with AOT, only real machines are supported, not simulators. All assertions are closed, debugging information is removed as much as possible, and all debugging tools are closed. The package size is optimized for fast startup and fast execution. All debugging aids and service extensions are prohibited.
Flutter Platform Channel
Platform Channel is used to realize the communication between flutter and Native, which is similar to remote communication.
Flutter defines three types of Channel:
BasicMessageChannel: for passing strings and semi-structured information
MethodChannel: for passing method calls (method invocation)
EventChannel: communication for data flow (event streams)
All three channel work the same way, using three basic attributes:
Name: String type, which represents the name of Channel and is its unique identifier
Messager:BinaryMessenger type, which stands for message messenger, is a tool for sending and receiving messages.
Codec: MessageCodec type or MethodCodec type, representing the codec of the message
BinaryMessenger is a tool for communication between Native and Flutter. The message format used for communication is binary format. When you initialize a Channel and register the Handler for processing messages with that Channel, you actually generate a corresponding BinaryMessageHandler and register it with channel name as the key in BinaryMessenger. When the fluter side sends a message to the BinaryMessenger, the BinaryMessenger will find the corresponding BinaryMessageHandler according to its input parameter channel and leave it to it for processing.
BinaryMessenger only communicates with BinaryMessageHandler. Channel and BinaryMessageHandler correspond to each other one by one. Because the message received by Channel from BinaryMessageHandler is in binary format and cannot be used directly, Channel decodes the binary message through Codec (message codec) into a recognizable message and passes it to Handler for processing.
When the Handler has finished processing the message, it returns result through the callback function, and encodes the result into binary format data through the codec, which is sent back to the fluter side through BinaryMessenger.
Codec: message codec, mainly used to convert data in binary format into data that Handler can recognize. Flutter defines two kinds of Codec:MessageCodec and MethodCodec.
MessageCodec is used to encode and decode between binary format data and underlying data. There are multiple implementations such as BinaryCodec, StringCodec, JSONMessageCodec, etc.
MethodCodec is used to encode and decode between binary data and method calls (MethodCall) and return results. The codecs used by MethodChannel and EventChannel are both MethodCodec.
MethodCodec is used to encode and decode MethodCall objects, and a MethodCall object represents a method call initiated from the fluter side. MethodCall has two member variables: method of type String represents the name of the method to be called, and arguments of common type (id in Android is id in Object,iOS) represents the input parameter of the method to be called.
Because you are dealing with method calls, MethodCodec has more processing of the result of the call. When the method call is successful, encodeSuccessEnvelope is used to encode result as binary data, and when the method call fails, encodeErrorEnvelope is used to encode the code, message, and detail of error into binary data.
There are two implementations of MethodCodec: JSONMethodCodec and StandardMethodCodec
Since Platform Channel runs in flutter App's UI Task Runner, the corresponding native implementation runs in Platform Task Runner, and Platform Task Runner runs in the main thread, time-consuming operations cannot be performed in the native implementation, and Platform Task Runner is non-thread safe, so make sure that the callback function is executed in the main thread.
Platform Channel supports big data transfer, using BasicMessageChannel and BinaryCodec when passing large memory blocks. In the whole process of data transmission, the only place where a copy of the data may occur is the conversion of native binary data to Dart language binary data. If the binary data is greater than the threshold (the current threshold is 1000byte), the data will not be copied and converted directly, otherwise a copy will be copied and then converted.
Thank you for reading! This is the end of this article on "what is flutter?". I hope the above content can be of some help to you, so that you can learn more knowledge. if you think the article is good, you can share it for more people to see!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.