监听者_DefaultInheritedProviderScopeElement监听到回调通知后通过markNeedsBuild()进行rebuild,而Consumer会通过Provider.of获取到最新的model值
graph LR
ChangeNotifierProvider("ChangeNotifierProvider_T extends ChangeNotifier_")-->|1:ListensTo|ChangeNotifier
ChangeNotifier-->|2:notifyListeners|ChangeNotifierProvider-->|3:rebuildsAndNotifyDependentsDescendants|Consumer
在_InheritedProviderScopeMixin被unmount时,会通知ChangeNotifier进行dispose,可以用来进行结构化并发,取消异步数据请求。
class Counter with ChangeNotifier {
int value = 0;
void increment() {
value += 1;
notifyListeners();
}
}
/// A class that can be extended or mixed in that provides a change notification
/// API using [VoidCallback] for notifications.
///
/// See also:
///
/// * [ValueNotifier], which is a [ChangeNotifier] that wraps a single value.
class ChangeNotifier implements Listenable {
LinkedList<_ListenerEntry>? _listeners = LinkedList<_ListenerEntry>();
/// Register a closure to be called when the object changes.
///
/// This method must not be called after [dispose] has been called.
@override
void addListener(VoidCallback listener) {
assert(_debugAssertNotDisposed());
_listeners.add(listener);
}
/// 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.
@override
void removeListener(VoidCallback listener) {
assert(_debugAssertNotDisposed());
_listeners.remove(listener);
}
/// 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());
_listeners = null;
}
}
@protected
@visibleForTesting
void notifyListeners() {
assert(_debugAssertNotDisposed());
if (_listeners != null) {
final List<VoidCallback> localListeners = List<VoidCallback>.from(_listeners);
for (VoidCallback listener in localListeners) {
if (_listeners.contains(listener))
listener();
void main() {
runApp(
// Provide the model to all widgets within the app. We're using
// ChangeNotifierProvider because that's a simple way to rebuild
// widgets when a model changes. We could also just use
// Provider, but then we would have to listen to Counter ourselves.
//
// Read Provider's docs to learn about all the available providers.
ChangeNotifierProvider(
// Initialize the model in the builder. That way, Provider
// can own Counter's lifecycle, making sure to call `dispose`
// when not needed anymore.
create: (context) => Counter(),
child: MyApp(),
),
);
}
/// Listens to a [ChangeNotifier], expose it to its descendants and rebuilds
/// dependents whenever [ChangeNotifier.notifyListeners] is called.
///
/// Depending on wether you want to **create** or **reuse** a [ChangeNotifier],
/// you will want to use different constructors.
ChangeNotifierProvider<T extends ChangeNotifier> extends ListenableProvider<T> {
/// Creates a [ChangeNotifier] using `create` and automatically
/// dispose it when [ChangeNotifierProvider] is removed from the widget tree.
///
/// `create` must not be `null`.
ChangeNotifierProvider({
Key key,
@required Create<T> create,
bool lazy,
Widget child,
}) : super(
key: key,
create: create,
dispose: _dispose,
lazy: lazy,
child: child,
);
}
/// A generic implementation of an [InheritedWidget].通过buildWithChild返回的Widget:_DefaultInheritedProviderScope实现InheritedWidget
/// Any descendant of this widget can obtain `value` using [Provider.of].
InheritedProvider<T> {
/// Creates a value, then expose it to its descendants.
///
/// The value will be disposed of when [InheritedProvider] is removed from
/// the widget tree.
InheritedProvider({
Key key,
Create<T> create,
T update(BuildContext context, T value),
UpdateShouldNotify<T> updateShouldNotify,
void Function(T value) debugCheckInvalidValueType,
StartListening<T> startListening,
Dispose<T> dispose,
bool lazy,
Widget child,
}) : _lazy = lazy,
_delegate = _CreateInheritedProvider(//main
create: create,//main
update: update,//main
updateShouldNotify: updateShouldNotify,
debugCheckInvalidValueType: debugCheckInvalidValueType,
startListening: startListening,
dispose: dispose,//main
),
super(key: key, child: child);
}
@override
Widget buildWithChild(BuildContext context, Widget child) {
return _DefaultInheritedProviderScope<T>(//main
owner: this,
child: child,
);
}
_DefaultInheritedProviderScope<T> extends InheritedWidget {
final InheritedProvider<T> owner;
@override
_DefaultInheritedProviderScopeElement<T> createElement() {
return _DefaultInheritedProviderScopeElement<T>(this);
}
}
_DefaultInheritedProviderScopeElement<T> extends InheritedElement with _InheritedProviderScopeMixin<T> {
}
@override
void performRebuild() {
if (_firstBuild) {
_firstBuild = false;
_mountDelegate();
}
super.performRebuild();
}
@override
void _mountDelegate() {
_delegateState = widget.owner._delegate.createState()..element = this;
}
_CreateInheritedProvider<T> {
@override
_CreateInheritedProviderState<T> createState() => _CreateInheritedProviderState();
}
@override
Widget build() {
if (_isLazy(widget) == false) {
value; // this will force the value to be computed. main
}
_delegateState.build(_isBuildFromExternalSources);
_isBuildFromExternalSources = false;
if (_shouldNotifyDependents) {
_shouldNotifyDependents = false;
notifyClients(widget);//main
}
return super.build();
}
@override
T get value => _delegateState.value;
@override
T get value {
if (!_didInitValue) {
_didInitValue = true;
if (delegate.create != null) {
_value = delegate.create(element);//main
}
if (delegate.update != null) {
_value = delegate.update(element, _value);//main
}
}
element._isNotifyDependentsEnabled = false;
_removeListener ??= delegate.startListening?.call(element, _value);//main
element._isNotifyDependentsEnabled = true;
return _value;
D get delegate => element._widgetToDelegate(element.widget) as D;
@override
_Delegate<T> _widgetToDelegate(_DefaultInheritedProviderScope<T> widget) {
return widget.owner._delegate;
}
static VoidCallback _startListening(
InheritedContext<Listenable> e,
Listenable value,
) {
value?.addListener(e.markNeedsNotifyDependents);//监听者_DefaultInheritedProviderScopeElement监听到回调通知后通过markNeedsBuild()进行rebuild,而Consumer会通过Provider.of获取到最新的model值
return () => value?.removeListener(e.markNeedsNotifyDependents);
}
@override
void markNeedsNotifyDependents() {
if (!_isNotifyDependentsEnabled) return;
markNeedsBuild();//main,performBuild-->updateChild-->update-->notifyClients逐个notify dependent
_shouldNotifyDependents = true;
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Demo Home Page'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('You have pushed the button this many times:'),
// Consumer looks for an ancestor Provider widget
// and retrieves its model (Counter, in this case).
// Then it uses that model to build widgets, and will trigger
// rebuilds if the model is updated.
Consumer<Counter>(//main
builder: (context, counter, child) => Text(
'${counter.value}',
style: Theme.of(context).textTheme.headline4,
),
),
],
),
),
//仅仅相当于Provider.of的封装,默认监听并会触发rebuild
Consumer<T> extends SingleChildStatelessWidget {
Consumer({
Key key,
@required this.builder,
Widget child,
}) : assert(builder != null),
super(key: key, child: child);
}
/// Build a widget tree based on the value from a [Provider<T>].
final Widget Function(BuildContext context, T value, Widget child) builder;
@override
Widget buildWithChild(BuildContext context, Widget child) {
return builder(
context,
Provider.of<T>(context),
child,
);
}
static T of<T>(BuildContext context, {bool listen = true}) {
InheritedContext<T> inheritedElement;
if (context.widget is _DefaultInheritedProviderScope<T>) {
// An InheritedProvider<T>'s update tries to obtain a parent provider of the same type.
context.visitAncestorElements((parent) {
inheritedElement = parent.getElementForInheritedWidgetOfExactType<_DefaultInheritedProviderScope<T>>()
as _DefaultInheritedProviderScopeElement<T>;
return false;
});
} else {
inheritedElement = context.getElementForInheritedWidgetOfExactType<_DefaultInheritedProviderScope<T>>()
as _DefaultInheritedProviderScopeElement<T>;
}
if (inheritedElement == null) {
throw ProviderNotFoundException(T, context.widget.runtimeType);
}
if (listen) {//main
context.dependOnInheritedElement(inheritedElement as InheritedElement);
}
return inheritedElement.value;