Flutter渲染原理深入解析
Widget Element RenderObject之間的關(guān)系
1 Widget
在Flutter 中,萬物皆是Widget,無論是可見的還是功能型的。一切都是Widget.
官方文檔中說的Widget 使用配置和狀態(tài)來描述View 界面應(yīng)該長什么樣子。
它不僅可以表示UI元素,也可以表示一些功能性的組件如:用于手勢檢測的 GestureDetector、用于APP主題數(shù)據(jù)傳遞的Theme、布局元素等等
兩個重要的方法
一個是通過 createElement 來創(chuàng)建 Element 對象的,
一個是根據(jù) key 來決定更新行為的 canUpdate 方法。
在這個方法中會對比runtimeType (也就是widget 的類型)和 key 是否相同
@immutable
abstract class Widget extends DiagnosticableTree {
/// Initializes [key] for subclasses.
const Widget({this.key});
final Key? key;
@protected
@factory
Element createElement();
/// A short, textual description of this widget.
@override
String toStringShort() {
final String type = objectRuntimeType(this, 'Widget');
return key == null ? type : '$type-$key';
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.defaultDiagnosticsTreeStyle = DiagnosticsTreeStyle.dense;
}
@override
@nonVirtual
bool operator ==(Object other) => super == other;
@override
@nonVirtual
int get hashCode => super.hashCode;
static bool canUpdate(Widget oldWidget, Widget newWidget) {
return oldWidget.runtimeType == newWidget.runtimeType &&
oldWidget.key == newWidget.key;
}
// Return a numeric encoding of the specific `Widget` concrete subtype.
// This is used in `Element.updateChild` to determine if a hot reload modified the
// superclass of a mounted element's configuration. The encoding of each `Widget`
// must match the corresponding `Element` encoding in `Element._debugConcreteSubtype`.
static int _debugConcreteSubtype(Widget widget) {
return widget is StatefulWidget
? 1
: widget is StatelessWidget
? 2
: 0;
}
}2 Element
Element 就是一個Widget 的實例,在樹中詳細(xì)的位置。
An instantiation of a Widget at a particular location in the tree
3 RenderObject
渲染樹上的一個對象。負(fù)責(zé)具體布局和繪制這些事情。
4 結(jié)合圖說一下其三者的關(guān)系


從創(chuàng)建到渲染的流程 :
根據(jù)Widget 生成Element,然后創(chuàng)建響應(yīng)的RenderObject并且關(guān)聯(lián)到Element.renderObject 屬性。最后再通過RenderObject 來完成布局和繪制。
依賴關(guān)系:
Element 樹根據(jù)Widget 樹生成,而渲染樹又依賴于widget 樹。
5 一些小問題
widget 和 element 是一一對應(yīng)的嗎 ? 為什么 ?
答:是一一對應(yīng)的。
因為 abstract class Widget ,本身是一個抽象類,這個抽象類中有一個抽象方法叫做createElement(),子類必須實現(xiàn)這個抽象方法,所以是一一對應(yīng)的。
widget 和 renderObject 是一一對應(yīng)的嗎 ? 為什么 ?
答:不是的
因為只有這個widget 繼承自RenderObjectWidget 的時候,才會有對應(yīng)的renderObject
像類似 Padding , Row,SizedBox,Center 這種組件繼承自RenderObjectWidget的組件會有一一對應(yīng)的關(guān)系
//class Padding extends SingleChildRenderObjectWidget // Padding(); // class Flex extends MultiChildRenderObjectWidget // Row()
BuildContext 是什么 ?
答:是Element,不管是StatefulWidget 還是StatelessWidget 都會重寫父類的build 方法,
build 方法傳入的一個參數(shù)叫做BuildContext, 我們拿StatelessWidget來說,其本身創(chuàng)建一個StatelessElement,而在這個Element內(nèi)部重寫StatelessElement父類的build方法,而在這個build方法內(nèi)部會調(diào)用_widget.build 方法,并且把this傳遞進去。那么這個this 就是element 。
/// An [Element] that uses a [StatelessWidget] as its configuration.
class StatelessElement extends ComponentElement {
/// Creates an element that uses the given widget as its configuration.
StatelessElement(StatelessWidget super.widget);
@override
Widget build() => (widget as StatelessWidget).build(this);
@override
void update(StatelessWidget newWidget) {
super.update(newWidget);
assert(widget == newWidget);
_dirty = true;
rebuild();
}
}Widget 頻繁更改創(chuàng)建是否會影響性能?復(fù)用和更新機制是什么樣的?
不會影響性能,因為只是一些配置信息,沒有有布局渲染到頁面上去。中間層Element 會通過widget 的runtimeType 和 Key 來對比是否進行更新操作。
Build 方法會在什么時候調(diào)用 ?
Element 創(chuàng)建完畢之后會調(diào)用mount 方法,對于非渲染的ComponentElement 來說,mount主要執(zhí)行的是Widget 中的build 方法。在StatelessElement 中直接使用的是 widget.build(this),
而在StatefullWidget 方法中,通過的是state.build(this)。在StatefulElement 這個類中,
初始化列表的給state 進行了賦值操作。通過widget調(diào)用createState方法之后,把state賦值給自己的_state 屬性。
StatefulElement(StatefulWidget widget)
: _state = widget.createState(),
createState 方法什么時候調(diào)用?
答:創(chuàng)建Element 的時候。
Flutter 會在遍歷 Widget 樹時調(diào)用 Widget 里面的 createElement 方法去生成對應(yīng)節(jié)點的 Element 對象,同時執(zhí)行 StatefulWidget 里面的 createState 方法創(chuàng)建 state,并且賦值給 Element 里的 _state 屬性,當(dāng)前 widget 也同時賦值給了 state 里的_widget,state 里面有個 widget 的get 方法可以獲取到 _widget 對象。
到此這篇關(guān)于Flutter渲染原理深入解析的文章就介紹到這了,更多相關(guān)Flutter渲染原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android Studio中CodeStyle模板的配置方式
這篇文章主要介紹了Android Studio中CodeStyle模板的配置方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03
一文理解Android系統(tǒng)中強指針的實現(xiàn)
因為Android中很多地方代碼是用C++編寫,為了能夠保證C++中指針能夠被正確的釋放,于是Android引入了其實在C++中已經(jīng)有的智能指針技術(shù)2021-10-10
Android 中WebView 截圖的實現(xiàn)方式
這篇文章主要介紹了Android 中WebView 截圖的實現(xiàn)方式,WebView 作為一種特殊的控件,自然不能像其他系統(tǒng) View 或者截屏的方式來獲取截圖。本文通過實例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧2017-12-12
Android 字符串中某個字段可點擊和設(shè)置顏色的方法
在android開發(fā)中,我們時常會遇到對字符串中某些固定的字段實現(xiàn)可點擊和顏色的設(shè)置,現(xiàn)粘貼處我在開發(fā)中如何設(shè)置這些屬性的2017-07-07
Android studio實現(xiàn)兩個界面間的切換
這篇文章主要為大家詳細(xì)介紹了Android studio實現(xiàn)兩個界面間的切換,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-04-04

