Flutter源碼分析筆記:Widget類源碼分析

Flutter源碼分析筆記
Widget類源碼分析

- 文章信息 - Author: 李俊才 (jcLee95)
Visit me at: https://jclee95.blog.csdn.net
Email: 291148484@163.com.
Shenzhen China
Address of this article:https://blog.csdn.net/qq_28550263/article/details/132259681

【介紹】:本文記錄閱讀與分析Flutter源碼 - Widget類源碼分析。


1. 概述

Widget類是Flutter框架中的核心類之一,用于描述用戶界面的一部分。它是一個不可變的描述,可以被實例化為元素(Element),后者負責管理底層的渲染樹。

Widget是Flutter框架的基礎,用于描述用戶界面的一部分,不可變且無狀態。它有一些用于實例化元素、診斷調試和比較的方法和屬性,同時它的子類可以是StatelessWidget或StatefulWidget,用于構建靜態或有狀態的用戶界面部分。

這部分源碼見附錄F-1。

2. 屬性

2.1 key

key屬性控制一個widget如何替換樹中的另一個widget。如果兩個widget的runtimeType和key屬性分別通過operator==比較是相等的,那么新的widget將通過更新底層元素來替換舊的widget。否則,舊的元素會從樹中移除,新的widget會被實例化為元素,然后插入樹中。

3. 方法

3.1 createElement()

該方法將配置實例化為一個具體的元素(Element)。一個widget可以在樹中被包含零次或多次,每次被包含在樹中時,都會被實例化為一個元素。

3.2 canUpdate(Widget oldWidget, Widget newWidget)

該方法用于判斷一個新的widget是否可以用來更新一個已有元素的配置。根據runtimeType和key屬性的比較來判斷兩個widget是否可以更新。

3.3 debugFillProperties(DiagnosticPropertiesBuilder properties)

debugFillProperties(DiagnosticPropertiesBuilder properties):向診斷信息屬性構建器添加屬性,用于調試和診斷。在子類中可以重寫以提供更多的調試信息。

3.4 _debugConcreteSubtype(Widget widget)

返回一個數值,表示特定Widget子類型的具體編碼。用于在熱重載時判斷已掛載元素的配置是否被修改。

3.5 其它

operator ==(Object other) 和 get hashCode

實現運算符”==“用于判斷兩個widget是否相等,以及計算它們的哈希值。

toStringShort()

返回此widget的簡短文本描述,通常是它的runtimeType和key的組合。

4. 繼承關系

4.1 Widget的父類

Widget 是一個抽象類,繼承自 DiagnosticableTree(這個類表示診斷樹,主要用于提供調試信息),因此繼承了一些用于調試和診斷的方法和屬性。

4.2 Widget的子類

4.2.1 StatefulWidget 和 StatelessWidget

Widget 本身沒有可變狀態,它的所有字段都必須是 final。如果需要關聯可變狀態,應該使用 StatefulWidget,后者在被實例化為元素并添加到樹中時會創建一個State對象。Widget的子類可以是 StatelessWidget(始終以相同的方式構建)或 StatefulWidget(可以在其生命周期內多次構建)。

在這里插入圖片描述
StatefulWidget: 這是一個帶有可變狀態的 Widget 類別。它由兩部分組成:一個是不可變的描述部分(Widget),另一個是可變的狀態部分(State)。StatefulWidget 實例在構建過程中可以改變其狀態,當狀態發生變化時,相關的 State 對象會被重新構建以更新界面。適用于有變化狀態的部分,比如用戶輸入、數據加載等。
StatelessWidget: 這是一個不可變的 Widget 類別,其描述和外觀在整個生命周期內保持不變。StatelessWidget 實例在構建時不會持有可變狀態,因此適用于不需要變化的 UI 部分,如圖標、文本等。

Widget可以被多次包含在樹中,每次都會被實例化為元素。如果某個 widget 在樹中出現多次,它將被多次實例化。

4.2.2 RenderObjectWidget

RenderObjectWidget是Flutter渲染引擎的一部分,表示屏幕上的可見對象,它又有LeafRenderObjectWidgetSingleChildRenderObjectWidgetMultiChildRenderObjectWidget這三個子類。
在這里插入圖片描述

  • LeafRenderObjectWidget: 這是一種將 RenderObject 無需管理子元素的 Widget 類別。它通常用于將自定義的繪制邏輯封裝為 Widget,然后通過構建 RenderObject 進行繪制。
  • SingleChildRenderObjectWidget: 這是一種管理單個子元素的 RenderObjectWidget 類別。它會創建一個單一的子元素,并將其作為子節點傳遞給 RenderObject 進行渲染。
  • MultiChildRenderObjectWidget: 這是一種管理多個子元素的 RenderObjectWidget 類別。它會創建多個子元素,并將它們作為子節點傳遞給 RenderObject 進行渲染。比如 Stack、Column 和 Row 等都是 MultiChildRenderObjectWidget 的子類。

4.2.3 ProxyWidget

ProxyWidget提供一種方式來包裝 Widgets,以實現特定的功能。它是一個具有子WidgetWidget,而非新的Widget

在這里插入圖片描述

  • ParentDataWidget: 這是一個用于修改子 Widget 布局約束的 ProxyWidget 子類。它在渲染樹中修改子元素的布局信息,例如 Positioned 和 Align 等都是 ParentDataWidget 的子類,用于指定子元素的位置和對齊方式。
  • InheritedWidget: 這是一種特殊類型的 ProxyWidget,它允許在 Widget 樹中向下傳遞共享的數據,而不需要顯式地傳遞。當 InheritedWidget 更新時,其子孫節點會自動重新構建。適用于需要在多個部分之間共享數據的情況,如主題、語言等。

5. Widget樹

Widget樹的概念

在Flutter中,Widget 樹是指由各種不同類型的Widget構成的層次結構。每個Widget描述了用戶界面的一部分,可以是一個簡單的元素,也可以是一個復雜的組合。這些Widget通過嵌套關系形成了一個樹狀結構,被稱為Widget樹。這種嵌套關系定義了界面中各個部分的排列和組織方式。

Widget樹是構建用戶界面的基本模型。當 Flutter 應用程序運行時,它會從一個 根Widget 開始,然后逐級構建出整個界面。每個Widget都有一個與之相關聯的Element,負責管理底層的渲染樹。渲染樹最終會被轉化為可視的UI元素,顯示在屏幕上。

Widget樹的特點

嵌套關系Widget 樹的節點由各種不同類型的 Widget 組成,這些 Widget 可以嵌套在彼此內部,形成層次結構。

不可變性Widget 本身是 不可變 的,一旦創建就不能再進行修改。如果需要更新界面,通常是通過創建新的Widget來替換舊的Widget。

構建方式: 構建 Widget 樹通常是通過構建方法來完成的。在構建方法中,你可以創建和組合不同的 Widget,從而構建出整個界面。

熱重載: Flutter支持熱重載,這意味著你可以在不重新啟動應用程序的情況下快速修改和查看界面的變化。在熱重載期間,Flutter會比較新舊Widget樹的差異,并盡可能地保留應用程序的狀態。

響應式: Flutter的界面是響應式的,意味著當數據發生變化時,相關的Widget會自動更新。這是通過在StatefulWidget 中管理可變狀態來實現的。

F. 附錄

F.1 Widget類源碼

abstract class Widget extends DiagnosticableTree {/// Initializes [key] for subclasses.const Widget({ this.key });/// Controls how one widget replaces another widget in the tree.////// If the [runtimeType] and [key] properties of the two widgets are/// [operator==], respectively, then the new widget replaces the old widget by/// updating the underlying element (i.e., by calling [Element.update] with the/// new widget). Otherwise, the old element is removed from the tree, the new/// widget is inflated into an element, and the new element is inserted into the/// tree.////// In addition, using a [GlobalKey] as the widget's [key] allows the element/// to be moved around the tree (changing parent) without losing state. When a/// new widget is found (its key and type do not match a previous widget in/// the same location), but there was a widget with that same global key/// elsewhere in the tree in the previous frame, then that widget's element is/// moved to the new location.////// Generally, a widget that is the only child of another widget does not need/// an explicit key.////// See also://////  * The discussions at [Key] and [GlobalKey].final Key? key;/// Inflates this configuration to a concrete instance.////// A given widget can be included in the tree zero or more times. In particular/// a given widget can be placed in the tree multiple times. Each time a widget/// is placed in the tree, it is inflated into an [Element], which means a/// widget that is incorporated into the tree multiple times will be inflated/// multiple times.Element createElement();/// A short, textual description of this widget.String toStringShort() {final String type = objectRuntimeType(this, 'Widget');return key == null ? type : '$type-$key';}void debugFillProperties(DiagnosticPropertiesBuilder properties) {super.debugFillProperties(properties);properties.defaultDiagnosticsTreeStyle = DiagnosticsTreeStyle.dense;}bool operator ==(Object other) => super == other;int get hashCode => super.hashCode;/// Whether the `newWidget` can be used to update an [Element] that currently/// has the `oldWidget` as its configuration.////// An element that uses a given widget as its configuration can be updated to/// use another widget as its configuration if, and only if, the two widgets/// have [runtimeType] and [key] properties that are [operator==].////// If the widgets have no key (their key is null), then they are considered a/// match if they have the same type, even if their children are completely/// different.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;}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:
http://www.pswp.cn/news/35530.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/35530.shtml
英文地址,請注明出處:http://en.pswp.cn/news/35530.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

TestNG和Junit5測試框架梳理

一、testNG 1. testNG優勢 注解驅動: TestNG 使用注解來標識測試方法、測試類和配置方法,使得測試更具可讀性。 并行執行: TestNG 支持多線程并行執行測試,可以加速測試套件的執行。 豐富的配置: 可以通過 XML 配置文…

Qt下載安裝及配置教程

進入qt中文網站:https://www.qt.io/zh-cn/ 下載開源版 往下滑,下載Qt在線安裝程序 它已經檢測出我的是windows系統,直接點擊download就好。如果是其它的系統,需要找到對應自己系統的安裝包。 然后跟網速有關,等…

Gitlab CI/CD筆記-第三天-使用主機docker in docker 進行構建并push鏡像。

一、啥叫docker in docker 就是允許的鏡像里頭有一個docker,但這個docekr鏡像只有docker的cli和/var/lib/docker.sock的套接字,沒有允許build.然后里頭又運行了一個docker,這個docker有build的能力,此時構建時就是里頭的docker使用外部的dock…

登錄驗證碼實現

Hutool代碼改造 Hutool 有參考文檔&#xff1b;很多工具類&#xff1b;把一些功能都封裝好&#xff1b;都不用你自己去寫&#xff1b;直接調用它的工具類 它這里會詳細告訴你引入方式Hutool <dependency><groupId>cn.hutool</groupId><artifactId>hu…

STM32F429IGT6使用CubeMX配置SPI通信(W25Q256芯片)

1、硬件電路 需要系統性的看一下W25Q256芯片手冊 2、設置RCC&#xff0c;選擇高速外部時鐘HSE,時鐘設置為180MHz 3、配置SPI 4、生成工程配置 5、相關代碼 #define sFLASH_ID 0XEF4019 // W25Q256#define SPI_FLASH_PageSize 256 #define SPI_FLASH_PerWritePageSize 256#def…

《雷達像智能識別對抗研究進展》閱讀記錄

&#xff08;1&#xff09;引言 ? 神經網絡通常存在魯棒性缺陷&#xff0c;易受到對抗攻擊的威脅。攻擊者可以隱蔽的誘導雷達智能目標識別做出錯誤預測&#xff0c;如&#xff1a; ? a圖是自行車&#xff0c;加上對抗擾動后神經網絡就會將其識別為挖掘機。 &#xff08;2&a…

【Quarkus技術系列】打造基于Quarkus的云原生微服務框架實踐(1)

前提介紹 本系列文章主要講解如何基于Quarkus技術搭建和開發"專為Kubernetes而優化的Java微服務框架"的入門和實踐&#xff0c;你將會學習到如何搭建Quarkus微服務腳環境及腳手架&#xff0c;開發Quarkus的端點服務&#xff0c;系統和應用層級的配置介紹與Quarkus的…

單芯片3路CC管理的VR轉接器解決方案

VR眼鏡即VR頭顯&#xff0c;也稱虛擬現實頭戴式顯示設備&#xff0c;隨著元宇宙概念的傳播&#xff0c;VR眼鏡的熱度一直只增不減&#xff0c;但是頭戴設備的續航一直被人詬病&#xff0c;如果增大電池就會讓頭顯變得笨重影響體驗&#xff0c;所以目前最佳的解決方案還是使用VR…

C# BeginInvoke 加 EndInvoke實現異步操作

1、定義一個委托 delegate long MyDel(int first, int second); 2、 需異步操作的函數 static int sum(int x,int y) {Console.WriteLine("InSide Sum1");Thread.Sleep(1000);Console.WriteLine("InSide Sum2");return x y;} 3、回調方法…

[HDLBits] Exams/m2014 q3

Consider the function f shown in the Karnaugh map below. Implement this function. d is dont-care, which means you may choose to output whatever value is convenient. //empty

gitui 解決 git error:Bad credentials.

問題描述 cat .git/config """ [remote "origin"]url gitgitcode.net:xxx.gitfetch refs/heads/*:refs/remotes/origin/* """ls -lh ~/.ssh/ """ -rw------- 1 z z 2.6K 8月 12 15:04 id_rsa -rw-r--r-- 1 z z 56…

學習左耳聽風欄目90天——第六天 6/90(學習左耳朵耗子的工匠精神,對技術的熱愛)【如何擁有技術領導力】

學習左耳聽風欄目90天——第六天 6/90&#xff08;學習左耳朵耗子的工匠精神&#xff0c;對技術的熱愛&#xff09;【如何擁有技術領導力】

【第358場周賽】限制條件下元素之間的最小絕對差,Java解密。

LeetCode 第358場周賽 恒生專場。 文章目錄 劍指Offer:限制條件下元素之間的最小絕對差示例:限制:解題思路:劍指Offer:限制條件下元素之間的最小絕對差 【題目描述】 給你一個下標從 0 開始的整數數組 nums 和一個整數 x 。 請你找到數組中下標距離至少為 x 的兩個元素的…

虛擬機內搭建CTFd平臺搭建及CTF題庫部署,局域網內機器可以訪問

一、虛擬機環境搭建 1、安裝docker、git、docker-compose ubuntu&#xff1a; sudo apt-get update #更新系統 sudo apt-get -y install docker.io #安裝docker sudo apt-get -y install git #安裝git sudo apt-get -y install python3-pip #安裝pip3 sudo pip install dock…

SQL筆記

最近的工作對SQL的應用程度較高&#xff0c;而且寫的sql類型基本沒怎么涉及過&#xff0c;把用到的幾個關鍵字記錄下。 使用環境&#xff1a;達夢數據庫 達夢數據庫有個特點&#xff0c;他有一個叫模式的說法&#xff0c;在圖形化工具里直接點擊創建查詢窗口&#xff0c;不用像…

Kubeadm安裝K8s集群

一、硬件環境 準備3臺Linux服務器&#xff0c;此處用Vmware虛擬機。 主機名CPU內存k8smaster2核4Gk8snode12核4Gk8snode22核4G 二、系統前置準備 配置三臺主機的hosts文件 cat << EOF > /etc/hosts 192.168.240.130 k8smaster 192.168.240.132 k8snode1 192.168.…

Sql奇技淫巧之ROWNUM偽列

ROWNUM偽列 ROWNUM是一個偽列&#xff0c;它是根據每次查詢的結果動態生成的一列遞增編號&#xff0c;表示 Oracle 從表中選擇該行的順序&#xff0c;選擇的第一行ROWNUM為1&#xff0c;第二行ROWNUM為2&#xff0c;以此類推。 注意1&#xff1a; ROWNUM偽列是在WHERE子句之…

torch.profiler

什么是torch.profiler PyTorch Profiler 是一個工具&#xff0c;它允許在訓練和推理期間收集性能指標。Profiler 的上下文管理器 API 可用于更好地了解哪些模型操作最昂貴&#xff0c;檢查它們的輸入形狀和調用堆棧&#xff0c;研究設備內核活動并可視化執行跟蹤。 性能指標&…

騰訊出品Pag動畫框架在Android端的使用-初級

Pag動畫框架作為一個第三方框架&#xff0c;它的優缺點與Lottie是相似&#xff0c;此處不過多贅述。如果你們的項目中打算用了&#xff0c;肯定是經過了一定的調研的。Pag動畫框架分幾個版本&#xff0c;有免費的有收費的。我們目前用的社區免費版&#xff0c;只用來展示Pag動畫…

項目實戰 — 消息隊列(8){網絡通信設計②}

目錄 一、客戶端設計 &#x1f345; 1、設計三個核心類 &#x1f345; 2、完善Connection類 &#x1f384; 讀取請求和響應、創建channel &#x1f384; 添加掃描線程 &#x1f384; 處理不同的響應 &#x1f384; 關閉連接 &#x1f345; 3、完善Channel類 &#x1f384; 編…