一.ChangeNotifier的简单介绍
ChangeNotifier是 Flutter SDK 中的一个简单的类。它用于向监听器发送通知。换言之,如果被定义为?ChangeNotifier,你可以订阅它的状态变化。(这和大家所熟悉的观察者模式相类似),了解更多请参考ChangeNotifier class - foundation library - Dart API
二.ChangeNotifier源码分析
1.addListener注册监听的方法,当对象改变的时候回调
/// Register a closure to be called when the object changes.
///
/// If the given closure is already registered, an additional instance is
/// added, and must be removed the same number of times it is added before it
/// will stop being called.
///
/// This method must not be called after [dispose] has been called.
///
/// {@template flutter.foundation.ChangeNotifier.addListener}
/// If a listener is added twice, and is removed once during an iteration
/// (e.g. in response to a notification), it will still be called again. If,
/// on the other hand, it is removed as many times as it was registered, then
/// it will no longer be called. This odd behavior is the result of the
/// [ChangeNotifier] not being able to determine which listener is being
/// removed, since they are identical, therefore it will conservatively still
/// call all the listeners when it knows that any are still registered.
///
/// This surprising behavior can be unexpectedly observed when registering a
/// listener on two separate objects which are both forwarding all
/// registrations to a common upstream object.
/// {@endtemplate}
///
/// See also:
///
/// * [removeListener], which removes a previously registered closure from
/// the list of closures that are notified when the object changes.
@override
void addListener(VoidCallback listener) {
assert(_debugAssertNotDisposed());
if (_count == _listeners.length) {
if (_count == 0) {
_listeners = List<VoidCallback?>.filled(1, null);
} else {
final List<VoidCallback?> newListeners =
List<VoidCallback?>.filled(_listeners.length * 2, null);
for (int i = 0; i < _count; i++) {
newListeners[i] = _listeners[i];
}
_listeners = newListeners;
}
}
_listeners[_count++] = listener;
}
2.removeListener,删除注册的监听,与addListener对应
/// Remove a previously registered closure from the list of closures that are
/// notified when the object changes.
///
/// If the given listener is not registered, the call is ignored.
///
/// This method must not be called after [dispose] has been called.
///
/// {@macro flutter.foundation.ChangeNotifier.addListener}
///
/// See also:
///
/// * [addListener], which registers a closure to be called when the object
/// changes.
@override
void removeListener(VoidCallback listener) {
assert(_debugAssertNotDisposed());
for (int i = 0; i < _count; i++) {
final VoidCallback? _listener = _listeners[i];
if (_listener == listener) {
if (_notificationCallStackDepth > 0) {
// We don't resize the list during notifyListeners iterations
// but we set to null, the listeners we want to remove. We will
// effectively resize the list at the end of all notifyListeners
// iterations.
_listeners[i] = null;
_reentrantlyRemovedListeners++;
} else {
// When we are outside the notifyListeners iterations we can
// effectively shrink the list.
_removeAt(i);
}
break;
}
}
}
3.dispose?丢弃对象使用的任何资源
/// Discards any resources used by the object. After this is called, the
/// object is not in a usable state and should be discarded (calls to
/// [addListener] and [removeListener] will throw after the object is
/// disposed).
///
/// This method should only be called by the object's owner.
@mustCallSuper
void dispose() {
assert(_debugAssertNotDisposed());
assert(() {
_debugDisposed = true;
return true;
}());
}
三.ChangeNotifierTest 实例
// ignore: file_names
import 'package:flutter/material.dart';
class Counter extends ChangeNotifier{
int _count =0;
int get count =>_count;
addCount(){
_count++;
notifyListeners();
}
}
Counter _counter=new Counter();
class ChangeNotifierTest extends StatefulWidget{
@override
_ChangeNotifierTestState createState() =>_ChangeNotifierTestState();
}
class _ChangeNotifierTestState extends State<ChangeNotifierTest>{
@override
void initState() {
// TODO: implement initState
super.initState();
_counter.addListener(() {//add listener
print('new count is :${_counter.count}');
});
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
_counter.dispose();//remove listener
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'ChangeNotifier test',
home: Scaffold(
appBar: AppBar(
title: Text('ChangeNotifier test bar'),
),
body: Center(
child: Container(
child: RaisedButton(
onPressed: (){
_counter.addCount();
},
child: Text('count')
),
),
),
),
);
}
}
|