2Provider

总结

监听者_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,可以用来进行结构化并发,取消异步数据请求。

ChangeNotifier

Usage

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;
 }
}

notifyListeners

@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();

ChangeNotifierProvider

Usage

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,
    );
}

InheritedProvider.buildWithChild

 /// 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.createElement

_DefaultInheritedProviderScope<T> extends InheritedWidget {
  final InheritedProvider<T> owner;
  
  @override
  _DefaultInheritedProviderScopeElement<T> createElement() {
    return _DefaultInheritedProviderScopeElement<T>(this);
   }
}

_DefaultInheritedProviderScopeElement.performRebuild

_DefaultInheritedProviderScopeElement<T> extends InheritedElement with _InheritedProviderScopeMixin<T> {
  
}
@override
 void performRebuild() {
  if (_firstBuild) {
   _firstBuild = false;
   _mountDelegate();
  }
  super.performRebuild();
 }

_mountDelegate

@override
 void _mountDelegate() {
  _delegateState = widget.owner._delegate.createState()..element = this;
 }
_CreateInheritedProvider.createState
_CreateInheritedProvider<T> {
  @override
 _CreateInheritedProviderState<T> createState() => _CreateInheritedProviderState();
}

build

@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();
}
value
@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;
 }
create T instance extends ChangeNotifier
startListening
static VoidCallback _startListening(
  InheritedContext<Listenable> e,
  Listenable value,
 ) {
  value?.addListener(e.markNeedsNotifyDependents);//监听者_DefaultInheritedProviderScopeElement监听到回调通知后通过markNeedsBuild()进行rebuild,而Consumer会通过Provider.of获取到最新的model值

 return () => value?.removeListener(e.markNeedsNotifyDependents);
 }
e.markNeedsNotifyDependents
@override
 void markNeedsNotifyDependents() {
  if (!_isNotifyDependentsEnabled) return;

  markNeedsBuild();//main,performBuild-->updateChild-->update-->notifyClients逐个notify dependent
  _shouldNotifyDependents = true;
 }

Consumer

Usage

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,
  );
}

Provider.of

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;