Flutter狀態管理篇之ChangeNotifier(二)

目錄

前言

一、ChangeNotifier定義

1.ChangeNotifier定義

2.Listenable的定義

二、繼承體系

三、核心方法解析

1.類結構與屬性分析

1.Listenable的定義

2..核心字段

1.屬性解析

1._count        

2._listeners

3.為什么不用const []

4._notificationCallStackDepth

5._reentrantlyRemovedListeners

6._debugDisposed

7._debugCreationDispatched

bool _debugCreationDispatched = false;

2. 方法解析

1.debugAssertNotDisposed

2.hasListeners

3.maybeDispatchObjectCreation

4.addListener

5.removeListener

6._removeAt

7.dispose

8.notifyListeners

3. 與_MergingListenable的關系

4. 設計理念和優化

5. 使用場景

6. 注意事項

7. 總結

四、生命周期管理

1. dispose()方法

五、內存跟蹤支持(調試)

六、總結

七、參考資料


前言

        上一篇博客介紹了ChangeNotifier的用法,這篇主要介紹ChangeNotifier的實現原理。

        那么,ChangeNotifier 是如何工作的?它內部又是如何維護監聽器并發送通知的?本文將從源碼角度出發,一步一步帶你深入理解 ChangeNotifier 的實現原理。

一、ChangeNotifier定義

1.ChangeNotifier定義

        ChangeNotifier 是一個混入類(mixin class),實現了 Listenable 接口,同時實現了Listenable定義的方法,具備添加、移除監聽器的能力。

mixin class ChangeNotifier implements Listenable

        它主要用于在數據發生變化時通知監聽者(Listener),從而驅動 UI 更新。

2.Listenable的定義

        我們看一下Listenable的定義,它是一個抽象類,定義了如下的方法:

以下是你提供的 Listenable 抽象類中所有注釋的中文翻譯版本:abstract class Listenable {/// 抽象的 const 構造函數。這個構造函數使得子類可以提供 const 構造函數,/// 以便它們可以在 const 表達式中使用。const Listenable();/// 返回一個 [Listenable],當給定的任意一個 [Listenable]/// 觸發時都會觸發該對象。////// 一旦調用了該工廠方法,不得再向可迭代對象中添加或移除項。/// 否則將導致內存泄漏或異常。////// 可迭代對象中可能包含 null,這些值會被忽略。factory Listenable.merge(Iterable<Listenable?> listenables) = _MergingListenable;/// 注冊一個回調函數,當對象通知其監聽者時會調用該回調。void addListener(VoidCallback listener);/// 從通知對象的回調列表中移除一個先前注冊的回調函數。void removeListener(VoidCallback listener);
}

        其中_MergingListenable類的定義如下,它使用一個數組_children保存Litenable類型的數組,當我們調用addListener方法的時候,把Listenable對象加入到數組中,當我們調用removeListener方法的時候,遍歷數組移除指定的Listenable。 除此之外,還提供了一個toString方法,用來調試。

class _MergingListenable extends Listenable {_MergingListenable(this._children);final Iterable<Listenable?> _children;@overridevoid addListener(VoidCallback listener) {for (final Listenable? child in _children) {child?.addListener(listener);}}@overridevoid removeListener(VoidCallback listener) {for (final Listenable? child in _children) {child?.removeListener(listener);}}@overrideString toString() {return 'Listenable.merge([${_children.join(", ")}])';}
}

二、繼承體系

        Flutter 中關于監聽的接口結構如下:

Listenable
├── ValueListenable<T>
│   └── ValueNotifier<T>
└── ChangeNotifier

        Listenable:最基礎的接口,定義了 addListener 和 removeListener 方法。

        ValueListenable<T>:擴展了 Listenable,增加了 value 屬性。

        ValueNotifier<T>:是一個封裝了 value 的 ChangeNotifier。

        ChangeNotifier:可以被繼承或混入,具備增刪監聽器及通知監聽器的功能。

三、核心方法解析

        這段代碼是 Flutter 中 ChangeNotifier 的核心實現之一,它實現了 Listenable 接口,并通過 mixin 的方式注入到模型類中。以下是對這份源碼的詳解,包括實現原理和內部機制:

1.類結構與屬性分析

1.Listenable的定義

mixin class ChangeNotifier implements Listenable

        使用 mixin class 是Dart 3引入的新特性,允許 mixin 具有構造函數,但此處它沒有構造函數。

        實現了Listenable 接口,因此需要實現 addListener、removeListener 方法。

2..核心字段

        ChangeNotifier中定義了幾個關鍵字段,用于管理監聽者列表和狀態:

1.屬性解析
1._count        

int _count = 0;

        作用:記錄當前注冊的監聽者數量。

        用途:_count 表示 _listeners 列表中實際有效的監聽者數量(不包括 null 占位符)。它用于快速判斷是否有監聽者(hasListeners)以及在添加/移除監聽者時更新列表狀態。

2._listeners

static final List<VoidCallback?> _emptyListeners = List<VoidCallback?>.filled(0, null);
List<VoidCallback?> _listeners = _emptyListeners;

        作用:存儲所有注冊的監聽者(VoidCallback類型,允許null)。
        初始化:

  1. _emptyListeners是一個靜態的空列表(長度為 0),用作初始值。

  2. _listeners是一個List<VoidCallback?>,允許存儲null,因為在某些情況下(例如通知期間移除監聽者),會臨時將列表中的某些位置設置為null。

3.為什么不用const []

        注釋中提到,const []會創建_ImmutableList類型的對象,而_listeners在運行時需要是固定長度的_GrowableList類型(盡管代碼中通過List.filled創建的是固定長度列表,但邏輯上允許動態調整大小)。
          保持_listeners的運行時類型一致(_GrowableList)有助于編譯器優化,提高性能。

4._notificationCallStackDepth

int _notificationCallStackDepth = 0;

        作用:跟蹤notifyListeners的遞歸調用深度。
        用途:用于處理通知期間的監聽者移除操作。如果在notifyListener執行期間移除監聽者,ChangeNotifier會延遲列表的實際縮減,直到所有通知完成(即_notificationCallStackDepth回到 0)。

5._reentrantlyRemovedListeners

int _reentrantlyRemovedListeners = 0;

   &nb

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

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

相關文章

大帶寬服務器對于高流量網站的作用

隨著科學技術的快速發展&#xff0c;越來越多的網站面臨著高流量的訪問需求&#xff0c;在同一時間中會有著大量的用戶進行訪問&#xff0c;同時也提高了該企業的知名度&#xff0c;但是這對于服務器的性能需求也在逐漸增高&#xff0c;而大帶寬服務器卓越的性能和穩定的傳輸能…

2025年算法備案發號規律總結與下半年發號預測

上半年發號規律總結圖太糊&#xff1f;可看下方表格&#xff08;左劃看全表&#xff09;&#x1f447;今年批次算法備案總批次發布時間所發當批算法材料提交時間段審核周期25年第一批第十批2025/3/122025年1月&#xff08;春節前&#xff09;約2個月25年第二批第十一批2025/5/1…

高光譜相機(Hyperspectral Camera)

高光譜相機&#xff08;Hyperspectral Camera&#xff09;高光譜相機&#xff1a;是一種可以采集連續、多達上百個窄波段的光譜信息的成像設備。它的核心特征是&#xff1a;每個像素點都擁有一個完整的光譜曲線&#xff0c;類似于“像素級別的光譜儀”。舉例&#xff1a;普通彩…

經典排序算法之歸并排序(Merge Sort)

歸并算法定義&#xff1a;所謂歸并排序是指將兩個或兩個以上有序的數列&#xff08;或有序表&#xff09;&#xff0c;合并成一個仍然有序的數列&#xff08;或有序表&#xff09;。這樣的排序方法經常用于多個有序的數據文件歸并成一個有序的數據文件。歸并排序相比較之前的排…

Linux系統環境下 Node.js 20 安裝實踐:glibc 2.17 兼容方案與工具鏈優化

前言&#xff1a;在 CentOS 7.9 的生產環境中&#xff0c;默認搭載的 glibc 2.17 是系統的核心依賴&#xff0c;直接升級它可能引發穩定性風險。而 Node.js 20 作為較新的運行時&#xff0c;其與 glibc 的兼容性長期困擾著開發者&#xff1a;為什么有些場景下 Node.js 20 能直接…

構建一個簡單的Java框架來測量并發執行任務的時間

文章目錄一、完整代碼二、代碼解釋1、方法簽名2、初始化CountDownLatch3、提交任務到執行器4、任務線程的邏輯5、主線程的邏輯詳細解釋總結以下代碼實現了一個簡單的框架&#xff0c;用于測量并發執行任務的時間。它使用了Executor來執行任務&#xff0c;并通過CountDownLatch來…

精通 triton 使用 MLIR 的源碼邏輯 - 第001節:triton 的應用簡介

項目使用到 MLIR&#xff0c;通過了解 triton 對 MLIR 的使用&#xff0c;體會到 MLIR 在較大項目中的使用方式&#xff0c;匯總一下。1. Triton 概述OpenAI Triton 是一個開源的編程語言和編譯器&#xff0c;旨在簡化 GPU 高性能計算&#xff08;HPC&#xff09; 的開發&#…

Python爬蟲-政務網站自動采集數據框架

前言 本文是該專欄的第81篇,后面會持續分享python爬蟲干貨知識,記得關注。 本文,筆者將詳細介紹一個基于政務網站進行自動采集數據的爬蟲框架。對此感興趣的同學,千萬別錯過。 廢話不多說,具體細節部分以及詳細思路邏輯,跟著筆者直接往下看正文部分。(附帶框架完整代碼…

GitHub 趨勢日報 (2025年07月19日)

&#x1f4ca; 由 TrendForge 系統生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日報中的項目描述已自動翻譯為中文 &#x1f4c8; 今日獲星趨勢圖 今日獲星趨勢圖1054shadPS4695n8n361remote-jobs321maigret257github-mcp-server249open_deep_res…

2025開源組件安全工具推薦OpenSCA

OpenSCA是國內最早的開源SCA平臺&#xff0c;繼承了商業級SCA的開源應用安全缺陷檢測、多級開源依賴挖掘、縱深代碼同源檢測等核心能力&#xff0c;通過軟件成分分析、依賴分析、特征分析、引用識別、合規分析等方法&#xff0c;深度挖掘組件中潛藏的各類安全漏洞及開源協議風險…

旅游管理實訓基地建設:筑牢文旅人才培養的實踐基石

隨著文旅產業的蓬勃發展&#xff0c;行業對高素質、強實踐的旅游管理人才需求日益迫切。旅游管理實訓基地建設作為連接理論教學與行業實踐的關鍵紐帶&#xff0c;既是深化產教融合的重要載體&#xff0c;也是提升旅游管理專業人才培養質量的核心抓手。一、旅游管理實訓基地建設…

網絡爬蟲的相關知識和操作

介紹 爬蟲的定義 爬蟲&#xff08;Web Crawler&#xff09;是一種自動化程序&#xff0c;用于從互聯網上抓取、提取和存儲網頁數據。其核心功能是模擬人類瀏覽行為&#xff0c;訪問目標網站并解析頁面內容&#xff0c;最終將結構化數據保存到本地或數據庫。 爬蟲的工作原理 …

【vue-6】Vue3 響應式數據聲明:深入理解 ref()

在 Vue3 的 Composition API 中&#xff0c;ref() 是最基礎也是最常用的響應式數據聲明方式之一。它為開發者提供了一種簡單而強大的方式來管理組件狀態。本文將深入探討 ref() 的工作原理、使用場景以及最佳實踐。 1. 什么是 ref()&#xff1f; ref() 是 Vue3 提供的一個函數&…

HTML常用標簽匯總(精簡版)

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>簡單標記</title> </head><body>&…

【.net core】支持通過屬性名稱索引的泛型包裝類

類/// <summary> /// 支持通過屬性名稱索引的泛型包裝類 /// </summary> public class PropertyIndexer<T> : IEnumerable<T> {private T[] _items;private T _instance;private PropertyInfo[] _properties;private bool _caseSensitive;public Prope…

【機器學習|學習筆記】詳解支持向量機(Support Vector Machine,SVM)為何要引入核函數?為何對缺失數據敏感?

【機器學習|學習筆記】詳解支持向量機(Support Vector Machine,SVM)為何要引入核函數?為何對缺失數據敏感? 【機器學習|學習筆記】詳解支持向量機(Support Vector Machine,SVM)為何要引入核函數?為何對缺失數據敏感? 文章目錄 【機器學習|學習筆記】詳解支持向量機(…

Bicep入門篇

前言 Azure Bicep 是 ARM 模板的最新版本,旨在解決開發人員在將資源部署到 Azure 時遇到的一些問題。它是一款開源工具,實際上是一種領域特定語言 (DSL),它提供了一種聲明式編寫基礎架構的方法,該基礎架構描述了虛擬機、Web 應用和網絡接口等云資源的拓撲結構。它還鼓勵在…

命名實體識別15年研究全景:從規則到機器學習的演進(1991-2006)

本文精讀NRC Canada與NYU聯合發表的經典綜述《A survey of named entity recognition and classification》&#xff0c;解析NERC技術演進脈絡與核心方法論 一、為什么命名實體識別&#xff08;NER&#xff09;如此重要&#xff1f; 命名實體識別&#xff08;Named Entity Rec…

eNSP綜合實驗(DNCP、NAT、TELET、HTTP、DNS)

1搭建實驗拓撲2實驗目的學習掌握eNSP中的命令3實驗步驟3.1配置連接PC和客戶端的交換機(僅以右側為例)[Huawei]vlan batch 10 20 #創建vlan Info: This operation may take a few seconds. Please wait for a moment...done. [Huawei]un in en [Huawei]interface e0/0/2 [Huawei…

無人系統與安防監控中的超低延遲直播技術應用:基于大牛直播SDK的實戰分享

技術背景 在 無人機、機器人 以及 智能安防 等高要求行業&#xff0c;高清視頻的超低延遲傳輸 正在成為影響系統性能與業務決策的重要因素。無論是工業生產線的遠程巡檢、突發事件的應急響應&#xff0c;還是高風險環境下的智能監控與遠程控制&#xff0c;視頻鏈路的傳輸延遲都…