目錄
前言
一、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)。
初始化:
-
_emptyListeners是一個靜態的空列表(長度為 0),用作初始值。
-
_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