1、Widget
StatelessWidget和StatefulWidget都繼承自Widget。
Widget作為虛類,定義了Element createElement()方法,給繼承者實(shí)現(xiàn),返回Element對象。
具體到StatelessWidget,實(shí)現(xiàn)createElement,返回StatelessElement對象。StatelessElement繼承自ComponentElement。
具體到StatefulWidget,實(shí)現(xiàn)createElement,返回StatefulElement對象。StatefulElement繼承自ComponentElement。
ComponentElement繼承自Element類。
在執(zhí)行createElement方法時,都會把Widget傳遞給Element對象,因此Element持有一個Widget對象。
2、Element
在Element樹的特定位置,Element代表一個Widget實(shí)例。
多個Element形成了一顆Element樹,大多數(shù)Element有一個獨(dú)一無二的child,但是那些繼承自RenderObjectElement的Element,就可以有多個child.
通過調(diào)用Widget.createElement方法創(chuàng)建一個Element,通過調(diào)用Element的mount方法,將一個新的Element添加到一個父Element的屬性為slot的位置。
Element類的mount方法,負(fù)責(zé)填充所有的子Widget,并在必要時調(diào)用attachRenderObject方法,將關(guān)聯(lián)的渲染對象(render objects)附著到渲染樹,此時Element被標(biāo)記為“active”,然后在屏幕上顯示。
3、RenderObject
渲染樹中的一個對象,通過RenderObjectToWidgetAdapter將其和Element聯(lián)系起來。渲染樹的根是RenderView,他有一個唯一的child,是RenderBox類型。在繪制階段,將RenderObject生成對應(yīng)的Layer tree,再將其生成Scene,交給GPU繪制。
總結(jié)
三者之間的基本關(guān)系就是:Element持有Widget對象,在Element的mount階段,通過Widget對象創(chuàng)建RenderObject對象,這個對象被Element持有。所以Element持有Widget和RenderObject對象。
Element管理著Widget生命周期,在生命周期不同階段,處理RenderObject不同的渲染繪制任務(wù)。
4、啟動
首先從main.dart的main方法開始運(yùn)行:
void main() {
runApp(MyApp());
}
runApp方法是在一個binding.dart文件里面:
packages\flutter\lib\src\widgets\binding.dart
void runApp(Widget app) {
WidgetsFlutterBinding.ensureInitialized()
..scheduleAttachRootWidget(app)
..scheduleWarmUpFrame();
}
4.1 WidgetsFlutterBinding
packages\flutter\lib\src\widgets\binding.dart
WidgetsFlutterBinding類調(diào)用靜態(tài)初始化方法,執(zhí)行初始化操作:
class WidgetsFlutterBinding extends BindingBase with GestureBinding, ServicesBinding, SchedulerBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding {
static WidgetsBinding ensureInitialized() {
if (WidgetsBinding.instance == null)
WidgetsFlutterBinding();
return WidgetsBinding.instance;
}
}
with關(guān)鍵字類似于java里面的implement關(guān)鍵字,可以初始化及調(diào)用with后面類的方法。如果對于這個關(guān)鍵字比較陌生的話,可以寫下面的demo代碼驗(yàn)證一下,看看初始化順序是怎么樣的:
abstract class Test1{
Test1(){
print("parent class");
init();
}
void init(){
print("class init");
}
}
mixin Demo1 on Test1{
void init(){
print("demo1 init");
super.init();
print("demo1 init done");
}
}
mixin Demo2 on Test1,Demo1 {
void init(){
print("demo2 init");
super.init();
print("demo2 init done");
}
}
class Test2 extends Test1 with Demo1,Demo2{
Test2(){
print("child class");
}
static void test(){
Test2();
}
}
void main() {
Test2.test();
}
parent class
demo2 init
demo1 init
class init
demo1 init done
demo2 init done
child class
透過demo我們可以知道,調(diào)用順序是先調(diào)用父類構(gòu)造函數(shù),然后with后面的類,從后往前調(diào)用,但是因?yàn)樵诿總€binding類的initInstances方法中,都先調(diào)用了super.initInstances方法,所以實(shí)際上先執(zhí)行前面的binding類代碼。先看看BindingBase的構(gòu)造函數(shù):
packages\flutter\lib\src\foundation\binding.dart
BindingBase() {
initInstances();
}
到這里開始執(zhí)行with從前到后binding的initInstances方法。
4.2 GestureBinding
綁定手勢子系統(tǒng),當(dāng)一個點(diǎn)按下事件從window傳遞過來之后,被其攔截,由GestureBinding決定在哪一個節(jié)點(diǎn)生效。
@override
void initInstances() {
super.initInstances();
_instance = this;
window.onPointerDataPacket = _handlePointerDataPacket;
}
獲取window窗口的onPointerDataPacket方法。
4.3 ServicesBinding
監(jiān)聽系統(tǒng)消息,并通過BinaryMessenger轉(zhuǎn)發(fā)。
@override
void initInstances() {
super.initInstances();
_instance = this;
_defaultBinaryMessenger = createBinaryMessenger();
window
..onPlatformMessage = defaultBinaryMessenger.handlePlatformMessage;
initLicenses();
SystemChannels.system.setMessageHandler(handleSystemMessage);
}
通過createBinaryMessenger方法創(chuàng)建了一個默認(rèn)的消息傳遞者。
4.4 SchedulerBinding
調(diào)度管理。調(diào)度分為幾個階段,分別是:
- 沒有frame需要處理的時候,處于Idle。
- transientCallbacks,暫時的回調(diào),比如更新RenderObject狀態(tài)到animate。
- midFrameMicrotasks,中間幀微服務(wù),比如正在處理暫時回調(diào)任務(wù)的時候。
- persistentCallbacks,持續(xù)性回調(diào),比如layer在創(chuàng)建,布局,繪制階段。
- postFrameCallbacks,清理,并準(zhǔn)備下一幀。
@override
void initInstances() {
super.initInstances();
_instance = this;
SystemChannels.lifecycle.setMessageHandler(_handleLifecycleMessage);
readInitialLifecycleStateFromNativeWindow();
if (!kReleaseMode) {
int frameNumber = 0;
addTimingsCallback((List<FrameTiming> timings) {
for (FrameTiming frameTiming in timings) {
frameNumber += 1;
_profileFramePostEvent(frameNumber, frameTiming);
}
});
}
}
4.5 PaintingBinding
綁定了繪制庫。
hook了緩存清理邏輯,用于清理圖片緩存。
@override
void initInstances() {
super.initInstances();
_instance = this;
_imageCache = createImageCache();
if (shaderWarmUp != null) {
shaderWarmUp.execute();
}
}
初始化方法中創(chuàng)建了圖片緩存對象,設(shè)置默認(rèn)圖片緩存大小。
shaderWarmUp其實(shí)是一個著色器預(yù)處理。在正式運(yùn)行app之前,先生成一個著色器ShaderWarmUp,繪制一個場景(Scene)到里面,并緩存起來。當(dāng)app里面有復(fù)雜的場景需要著色時,可以減少動畫或交互時的卡頓。
著色預(yù)熱操作是在GPU線程里面同步操作的,意味著,app第一幀的渲染必須等到該操作完成之后才能繼續(xù)。
4.6 SemanticsBinding
Semantics是語義的意思。這個類將語義層(semantics layer)與flutter engine聯(lián)系起來。
@override
void initInstances() {
super.initInstances();
_instance = this;
_accessibilityFeatures = window.accessibilityFeatures;
}
4.7 RendererBinding
packages\flutter\lib\src\rendering\binding.dart
將渲染樹和Flutter engine聯(lián)系起來。
@override
void initInstances() {
super.initInstances();
_instance = this;
_pipelineOwner = PipelineOwner(
onNeedVisualUpdate: ensureVisualUpdate,
onSemanticsOwnerCreated: _handleSemanticsOwnerCreated,
onSemanticsOwnerDisposed: _handleSemanticsOwnerDisposed,
);
window
..onMetricsChanged = handleMetricsChanged
..onTextScaleFactorChanged = handleTextScaleFactorChanged
..onPlatformBrightnessChanged = handlePlatformBrightnessChanged
..onSemanticsEnabledChanged = _handleSemanticsEnabledChanged
..onSemanticsAction = _handleSemanticsAction;
initRenderView();
_handleSemanticsEnabledChanged();
assert(renderView != null);
addPersistentFrameCallback(_handlePersistentFrameCallback);
initMouseTracker();
}
看看幾個關(guān)鍵的類。
4.7.1 PipelineOwner
packages\flutter\lib\src\rendering\object.dart
PipelineOwner管理著渲染流程。
PipelineOwner對外提供接口用于驅(qū)動渲染流程。并存儲著那些請求訪問渲染流程中各個階段的狀態(tài)??梢酝ㄟ^以下步驟來刷新渲染流程:
- flushLayout
更新任何需要重新計(jì)算布局的渲染對象。在這個階段渲染對象的大小和布局都被計(jì)算好了。在此階段,渲染對象的繪制和合成狀態(tài)被置成dirty。
- flushCompositingBits
渲染對象的復(fù)合bit被設(shè)置成dirty狀態(tài)之后會在這個階段更新,并且每一個渲染對象都可以知道自己的子對象是否需要被復(fù)合。這個信息在繪制階段執(zhí)行裁剪的時候會起到作用。
- flushPaint
訪問那些需要被繪制的渲染對象。在這個階段,這些渲染對象有機(jī)會記錄繪制命令到PictureLayer,以及組建其他復(fù)合Layer。
- flushSemantics
最后,如果啟用了語義,該階段將編譯渲染對象的語義。 該語義信息由輔助技術(shù)可改善渲染樹的可訪問性。
4.7.2 RenderView
接下來會執(zhí)行initRenderView方法,創(chuàng)建一個RenderView對象,他繼承自RenderObject類,是整個渲染樹的根。
void initRenderView() {
renderView = RenderView(configuration: createViewConfiguration(), window: window);
renderView.prepareInitialFrame();
}
接下來RenderView的對象還調(diào)用了prepareInitialFrame方法,如下:
packages\flutter\lib\src\rendering\view.dart
void prepareInitialFrame() {
scheduleInitialLayout();
scheduleInitialPaint(_updateMatricesAndCreateNewRootLayer());
}
- scheduleInitialLayout方法:
packages\flutter\lib\src\rendering\object.dart
void scheduleInitialLayout() {
_relayoutBoundary = this;
owner._nodesNeedingLayout.add(this);
}
這個方法屬于RenderObject類,由此我們看到RenderView實(shí)際調(diào)用的是父類的方法,而這個owner就是我們在initInstances方法中初始化的PipelineOwner類的對象。
_nodesNeedingLayout是一個RenderObject對象的List,全局已經(jīng)初始化了,在這里先將RenderView對象添加進(jìn)去,作為根。
- _updateMatricesAndCreateNewRootLayer方法
在調(diào)用scheduleInitialPaint方法之前先調(diào)用_updateMatricesAndCreateNewRootLayer新建一個Layer對象:
packages\flutter\lib\src\rendering\view.dart
Layer _updateMatricesAndCreateNewRootLayer() {
_rootTransform = configuration.toMatrix();
final ContainerLayer rootLayer = TransformLayer(transform: _rootTransform);
rootLayer.attach(this);
return rootLayer;
}
ContainerLayer其實(shí)是一個復(fù)合的Layer,可以包含很多子Layer。另外Layer繼承自AbstractNode。
- scheduleInitialPaint方法:
packages\flutter\lib\src\rendering\object.dart
void scheduleInitialPaint(ContainerLayer rootLayer) {
_layer = rootLayer;
owner._nodesNeedingPaint.add(this);
}
_nodesNeedingPaint是一個RenderObject對象的List,全局已經(jīng)初始化了,在這里先將一個RenderView對象添加進(jìn)去,另外可以看到RenderObject持有一個Layer對象。
4.7.3 addPersistentFrameCallback方法
回到RendererBinding的initInstances方法中,addPersistentFrameCallback方法添加回調(diào),回調(diào)方法是_handlePersistentFrameCallback。
addPersistentFrameCallback方法則是把這個回調(diào)放到List中存起來,在SchedulerBinding的_persistentCallbacks階段集中調(diào)用:
final List<FrameCallback> _persistentCallbacks = <FrameCallback>[];
void addPersistentFrameCallback(FrameCallback callback) {
_persistentCallbacks.add(callback);
}
_handlePersistentFrameCallback方法里面調(diào)用的就是drawFrame方法。
4.8 WidgetsBinding
packages\flutter\lib\src\widgets\binding.dart
將widget layer與flutter engine融合在一起。
initInstances方法:
packages\flutter\lib\src\widgets\binding.dart
void initInstances() {
super.initInstances();
_buildOwner = BuildOwner();
buildOwner.onBuildScheduled = _handleBuildScheduled;
}
BuildOwner類管理著widget的框架,比如跟蹤哪些widget需要重建,在全局處理應(yīng)用于widget樹的任務(wù),比如開發(fā)者在調(diào)試時啟動熱加載,就會組織那些渲染樹中不活躍的列表元素,并觸發(fā)重組指令。