目录
前言
一、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