Flutter 詳解(七、深入瞭解繪製原理)
Widget
在
flutter
中,every is widget
,理解起來很容易,我們所使用的顯示文字的Text
,展示圖片的Image
,展示位置資訊的Padding
,都是Widget
.
在閱讀Flutter原始碼的,你可能會注意到Widget
的定義:
@immutable abstract class Widget extends DiagnosticableTree { ... const Widget({ this.key }); final Key key; static bool canUpdate(Widget oldWidget, Widget newWidget) { return oldWidget.runtimeType == newWidget.runtimeType && oldWidget.key == newWidget.key; } ... }
官方這樣講:
A widget is an immutable description of part of a user interface.
小部件是對使用者介面的不可變的描述。
我們注意到左上角有@immutable
,這個很重要,視窗小部件中的所有屬性都必須為final
,一旦例項化,就無法跟更改內部屬性,但是事實上,我們的UI
不可能一成不變的,因此Flutter
如何管理UI
的狀態呢?
Flutter
有三棵樹,Widget
樹、Element
樹、RenderObjects
樹,這些樹分工不同,將他們組合在一起,來優化UI的各種可能性。
Element是什麼
記錄一個Widget的位置資訊
An instantiation of a [Widget] at a particular location in the tree.
它是樹的可變部分,用於管理UI
更新和更改,您可以將它看做是管理widget
的生命週期的元素。每個元素都引用了一個widget
,很簡單的。
RenderObject是什麼
在Flutter
繪製UI時,它不會檢視Widget
的樹,而是檢視RenderObjects
,它控制大小,佈局並保留用於繪製實際widget
的所有邏輯,這就是渲染物件例項化很好效能的原因。
為了更好的展示這三棵樹,我們看下面小部件:
class HomeRoute extends StatelessWidget { @override Widget build(BuildContext context) { return Center( child: Text('Hello world'), ); } }
當我們啟動應用時
1.Flutter
將遍歷您的視窗小部件並建立視窗小部件樹。
2. 與小部件對應,Flutter
建立元素樹,在其中通過createElement()
建立每一個Element
物件。
3. 當Element
呼叫createRenderObject()
時,將建立每個渲染物件。
如圖所示:
當我們要改變小部件Text
的值,我們看下Flutter Inspector
的資訊。
更改前:
更改後:
在text
中顯示的值從4
變為5
,它的renderObject
並未改變。
因為在例項化渲染物件很耗費效能,flutter
在這點做了保留,省掉了重複例項化的開銷,如果他們具有相同的型別,則無需重新建立渲染物件。我們只需要更新key
的值,可以做到重新建立渲染物件。
在實際開發中,一個頁面估計至少幾十個widget
,或者上百個widget
,那麼對應的element
和renderObject
也是數量相等的,因此重新建立整個樹是非常消耗效能的,flutter最大程度減小效能浪費,從而獲得更佳的UI
效能。
參考
文章彙總
<<Flutter 詳解(一、深入瞭解狀態管理--ScopeModel)>>
<<Flutter 詳解(二、深入瞭解狀態管理--Redux)>>
<<Flutter 詳解(三、深入瞭解狀態管理--Provider)>>
<<Flutter 詳解(四、深入瞭解狀態管理--BLoC)>>