1 什么是状态?什么是状态管理?
数据即为状态。从数据变化到通知界面更新的过程,我们称之为状态管理,状态管理要尽可能的把这个过程独立出来,让动态界面如同静态页面一般简单。
大到页面的路由变化,小到页面的数据发生变化,我们开发中每时每刻都离不开状态,有一位伟人曾说过,一切皆数据,那么今天就让我们从浅入深的揭开状态管理的神秘面纱。
如果还完全没有使用过Provider的同学请移步:新手入门
2 从Provider看状态管理
import 'package:flutter/material.dart';
class MyModel3 with ChangeNotifier {
MyModel3({this.counter=0});
int counter = 0;
Future<void> incrementCounter() async {
// await Future.delayed(Duration(seconds: 2));
counter++;
print(counter);
notifyListeners();
}
@override
void dispose() {
// TODO: implement dispose
print('MyModel3 dispose');
super.dispose();
}
}
class ProviderDebugPage3 extends StatelessWidget {
final String title;
ProviderDebugPage3({this.title});
@override
Widget build(BuildContext context) {
print('---provider build ---');
return ChangeNotifierProvider(
create: (context) => MyModel3(),
child: Scaffold(
appBar: AppBar(
title: Text(this.title),
),
body: Column(
children: <Widget>[
Consumer<MyModel3>(
// 获取到provider提供出来的值
builder: (context, model, child) {
return Container(
margin: const EdgeInsets.only(top: 20),
width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.all(20),
alignment: Alignment.center,
color: Colors.lightGreen,
child: Text(
'Model3当前是:${model.counter}',
),
);
},
),
Consumer<MyModel3>(
// 获取到provider提供出来的值
builder: (context, model, child) {
return FlatButton(
color: Colors.tealAccent,
onPressed: model.incrementCounter,
child: Icon(Icons.add));
},
),
],
),
),
);
}
}
上面是我们通常使用的ChangeNotifierProvider,这里用到了3个类ChangeNotifierProvider、ChangeNotifier、Consumer,其中核心类是ChangeNotifierProvider,它和ChangeNotifier是观察者模式,和Consumer是生产者消费者模式,达到的目的是,即使是StatelessWidget,当数据MyModel3发生变化时,对应的UI也能一起刷新,实现了从数据变化到更新UI的自动化过程,这里并不像我们使用StatefulWidget的setState,数据变化是自动引起UI刷新的,那么围绕核心类ChangeNotifierProvider,我们去源码一探究竟。

3 ChangeNotifierProvider 源码分析
class 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,
TransitionBuilder builder,
Widget child,
}) : super(
key: key,
create: create,
dispose: _dispose,
lazy: lazy,
builder: builder,
child: child,
);
/// Provides an existing [ChangeNotifier].
ChangeNotifierProvider.value({
Key key,
@required T value,
TransitionBuilder builder,
Widget child,
}) : super.value(
key: key,
builder: builder,
value: value,
child: child,
);
static void _dispose(BuildContext context, ChangeNotifier notifier) {
notifier?.dispose();
}
}
这里ChangeNotifierProvider是一个泛型类,泛型T是继承ChangeNotifier类的,ChangeNotifierProvider初始化的时候,多加了一个_dispose方法,其余参数都传给了父类ListenableProvider,这里解释了,为什么MyModel3在页面析构的时候也会自动调用dispose,是因为当系统回调ChangeNotifierProvider的_dispose方法时,_dispose里面调用了MyModel3 的dispose
3.1 ListenableProvider 源码分析
class ListenableProvider<T extends Listenable> extends InheritedProvider<T> {
/// Creates a [Listenable] using [create] and subscribes to it.
///
/// [dispose] can optionally passed to free resources
/// when [ListenableProvider] is removed from the tree.
///
/// [create] must not be `null`.
ListenableProvider({
Key key,
@required Create<T> create,
Dispose<T> dispose,
bool lazy,
TransitionBuilder builder,
Widget child,
}) : assert(create != null),
super(
key: key,
startListening: _startListening,
create: create,
dispose: dispose,
debugCheckInvalidValueType: kReleaseMode
? null
: (value) {
if (value is ChangeNotifier) {
// ignore: invalid_use_of_protected_member
assert(!value.hasListeners, '''
The default constructor of ListenableProvider/ChangeNotifierProvider
must create a new, unused Listenable.
If you want to reuse an existing Listenable, use the second constructor:
- DO use ChangeNotifierProvider.value to provider an existing ChangeNotifier:
MyChangeNotifier variable;
ChangeNotifierProvider.value(
value: variable,
child: ...
)
- DON'T reuse an existing ChangeNotifier using the default constructor.
MyChangeNotifier variable;
ChangeNotifierProvider(
create: (_) => variable,
child: ...
)
''');
}
},
lazy: lazy,
builder: builder,
child: child,
);
/// Provides an existing [Listenable].
ListenableProvider.value({
Key key,
@required T value,
UpdateShouldNotify<T> updateShouldNotify,
TransitionBuilder builder,
Widget child,
}) : super.value(
key: key,
builder: builder,
value: value,
updateShouldNotify: updateShouldNotify,
startListening: _startListening,
child: child,
);
static VoidCallback _startListening(
InheritedContext<Listenable> e,
Listenable value,
) {
value?.addListener(e.markNeedsNotifyDependents);
return () => value?.removeListener(e.markNeedsNotifyDependents);
}
}
同样是泛型类,在这里又增加了一个_startListening方法,实现是的功能是:
1 订阅事件,当接受到事件时,通知Element更新UI
2 返回一个默认取消订阅的回调
相比于ChangeNotifierProvider这里我们遇到InheritedContext和updateShouldNotify,先mark下,继续往下。
3.2 InheritedProvider 源码分析
class InheritedProvider<T> extends SingleChildStatelessWidget {
/// 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 Function(BuildContext context, T value) update,
UpdateShouldNotify<T> updateShouldNotify,
void Function(T value) debugCheckInvalidValueType,
StartListening<T> startListening,
Dispose<T> dispose,
this.builder,
bool lazy,
Widget child,
}) : _lazy = lazy,
_delegate = _CreateInheritedProvider(
create: create,
update: update,
updateShouldNotify: updateShouldNotify,
debugCheckInvalidValueType: debugCheckInvalidValueType,
startListening: startListening,
dispose: dispose,
),
super(key: key, child: child);
...省略以下代码
}
相比于ListenableProvider 这里参数又增加了update,并且出现了新的属性_delegate
看定义
final _Delegate<T> _delegate;
这里之前的参数都传给了_CreateInheritedProvider类,是个内部类,也就是官方不建议我们直接使用的
class _CreateInheritedProvider<T> extends _Delegate<T> {
_CreateInheritedProvider({
this.create,
this.update,
UpdateShouldNotify<T> updateShouldNotify,
this.debugCheckInvalidValueType,
this.startListening,
this.dispose,
}) : assert(create != null || update != null),
_updateShouldNotify = updateShouldNotify;
final Create<T> create;
final T Function(BuildContext context, T value) update;
final UpdateShouldNotify<T> _updateShouldNotify;
final void Function(T value) debugCheckInvalidValueType;
final StartListening<T> startListening;
final Dispose<T> dispose;
@override
_CreateInheritedProviderState<T> createState() =>
_CreateInheritedProviderState();
}
class _CreateInheritedProviderState<T>
extends _DelegateState<T, _CreateInheritedProvider<T>> {
VoidCallback _removeListener;
bool _didInitValue = false;
T _value;
_CreateInheritedProvider<T> _previousWidget;
}
至此,从ChangeNotifierProvider 传递进来的参数都存在了_CreateInheritedProvider里了,而_CreateInheritedProvider的父类是一个抽象类_Delegate
abstract class _Delegate<T> {
_DelegateState<T, _Delegate<T>> createState();
void debugFillProperties(DiagnosticPropertiesBuilder properties) {}
}
abstract class _DelegateState<T, D extends _Delegate<T>>
_DelegateState类也是泛型类,有两个泛型T和D,其中D是继承_Delegate<T>的,那我们看看具体的实现类_CreateInheritedProviderState
class _CreateInheritedProviderState<T>
extends _DelegateState<T, _CreateInheritedProvider<T>> {
VoidCallback _removeListener;
bool _didInitValue = false;
T _value;
_CreateInheritedProvider<T> _previousWidget;
@override
T get value {
bool _debugPreviousIsInInheritedProviderCreate;
bool _debugPreviousIsInInheritedProviderUpdate;
assert(() {
_debugPreviousIsInInheritedProviderCreate =
debugIsInInheritedProviderCreate;
_debugPreviousIsInInheritedProviderUpdate =
debugIsInInheritedProviderUpdate;
return true;
}());
if (!_didInitValue) {
_didInitValue = true;
if (delegate.create != null) {
assert(debugSetInheritedLock(true));
try {
assert(() {
debugIsInInheritedProviderCreate = true;
debugIsInInheritedProviderUpdate = false;
return true;
}());
_value = delegate.create(element);
} finally {
assert(() {
debugIsInInheritedProviderCreate =
_debugPreviousIsInInheritedProviderCreate;
debugIsInInheritedProviderUpdate =
_debugPreviousIsInInheritedProviderUpdate;
return true;
}());
}
assert(debugSetInheritedLock(false));
assert(() {
delegate.debugCheckInvalidValueType?.call(_value);
return true;
}());
}
if (delegate.update != null) {
try {
assert(() {
debugIsInInheritedProviderCreate = false;
debugIsInInheritedProviderUpdate = true;
return true;
}());
_value = delegate.update(element, _value);
} finally {
assert(() {
debugIsInInheritedProviderCreate =
_debugPreviousIsInInheritedProviderCreate;
debugIsInInheritedProviderUpdate =
_debugPreviousIsInInheritedProviderUpdate;
return true;
}());
}
assert(() {
delegate.debugCheckInvalidValueType?.call(_value);
return true;
}());
}
}
element._isNotifyDependentsEnabled = false;
_removeListener ??= delegate.startListening?.call(element, _value);
element._isNotifyDependentsEnabled = true;
assert(delegate.startListening == null || _removeListener != null);
return _value;
}
@override
void dispose() {
super.dispose();
_removeListener?.call();
if (_didInitValue) {
delegate.dispose?.call(element, _value);
}
}
@override
void build({bool isBuildFromExternalSources}) {
var shouldNotify = false;
// Don't call `update` unless the build was triggered from `updated`/`didChangeDependencies`
// otherwise `markNeedsNotifyDependents` will trigger unnecessary `update` calls
if (isBuildFromExternalSources &&
_didInitValue &&
delegate.update != null) {
final previousValue = _value;
bool _debugPreviousIsInInheritedProviderCreate;
bool _debugPreviousIsInInheritedProviderUpdate;
assert(() {
_debugPreviousIsInInheritedProviderCreate =
debugIsInInheritedProviderCreate;
_debugPreviousIsInInheritedProviderUpdate =
debugIsInInheritedProviderUpdate;
return true;
}());
try {
assert(() {
debugIsInInheritedProviderCreate = false;
debugIsInInheritedProviderUpdate = true;
return true;
}());
_value = delegate.update(element, _value);
} finally {
assert(() {
debugIsInInheritedProviderCreate =
_debugPreviousIsInInheritedProviderCreate;
debugIsInInheritedProviderUpdate =
_debugPreviousIsInInheritedProviderUpdate;
return true;
}());
}
if (delegate._updateShouldNotify != null) {
shouldNotify = delegate._updateShouldNotify(previousValue, _value);
} else {
shouldNotify = _value != previousValue;
}
if (shouldNotify) {
assert(() {
delegate.debugCheckInvalidValueType?.call(_value);
return true;
}());
if (_removeListener != null) {
_removeListener();
_removeListener = null;
}
_previousWidget?.dispose?.call(element, previousValue);
}
}
if (shouldNotify) {
element._shouldNotifyDependents = true;
}
_previousWidget = delegate;
return super.build(isBuildFromExternalSources: isBuildFromExternalSources);
}
@override
bool get hasValue => _didInitValue;
}
因为T get value还没用到,我们focus在build,由于父类_DelegateState是抽象类,这里重写了build方法,这里用到了两个属性,delegate和element,都是父类中定义的,delegate也是element中取到的
abstract class _DelegateState<T, D extends _Delegate<T>> {
_InheritedProviderScopeElement<T> element;
T get value;
D get delegate => element.widget.owner._delegate as D;
bool get hasValue;
bool debugSetInheritedLock(bool value) {
return element._debugSetInheritedLock(value);
}
bool willUpdateDelegate(D newDelegate) => false;
void dispose() {}
void debugFillProperties(DiagnosticPropertiesBuilder properties) {}
void build({@required bool isBuildFromExternalSources}) {}
}
那我们看看element是怎么来的,首先,类型是_InheritedProviderScopeElement<T>,我们找到创建对象的地方:_InheritedProviderScope中有个createElement方法可以返回这样的element,但从dart代码上我们没追踪到谁调用了createElement,我们先mark一下,谁调用了createElement
class _InheritedProviderScope<T> extends InheritedWidget {
const _InheritedProviderScope({
this.owner,
@required Widget child,
}) : super(child: child);
final InheritedProvider<T> owner;
@override
bool updateShouldNotify(InheritedWidget oldWidget) {
return false;
}
@override
_InheritedProviderScopeElement<T> createElement() {
return _InheritedProviderScopeElement<T>(this);
}
}
class _InheritedProviderScopeElement<T> extends InheritedElement
implements InheritedContext<T> {
_InheritedProviderScopeElement(_InheritedProviderScope<T> widget)
: super(widget);
bool _shouldNotifyDependents = false;
bool _debugInheritLocked = false;
bool _isNotifyDependentsEnabled = true;
bool _firstBuild = true;
bool _updatedShouldNotify = false;
bool _isBuildFromExternalSources = false;
_DelegateState<T, _Delegate<T>> _delegateState;
@override
_InheritedProviderScope<T> get widget =>
super.widget as _InheritedProviderScope<T>;
...以下代码省略
}
说到这个_InheritedProviderScope类,存在着继承关系:_InheritedProviderScope->InheritedWidget>ProxyWidget->Widget,本质上是一个Widget,在构造的时候,外面传入了owner,也就是InheritedProvider,这样就在Widget里面持有了InheritedProvider,那在创建_InheritedProviderScopeElement时传入了this,也就把InheritedProvider带给了InheritedElement(_InheritedProviderScopeElement的父类,继承关系:_InheritedProviderScopeElement->InheritedElement->ProxyElement->ComponentElement->Element->DiagnosticableTree),所以本质还是Element,如果对Widget、Element还不太清楚的,可以参考这篇文章,实际视图的刷新逻辑都是在Element中,本节我们暂不深入分析视图刷新的逻辑,先回到上说的_CreateInheritedProviderState另外一个属性delegate,
D get delegate => element.widget.owner._delegate as D;
这里我们看到,之前element持有了_InheritedProviderScope的widget,widget的owner是InheritedProvider,element.widget.owner._delegate就是InheritedProvider的属性_delegate,是通过_CreateInheritedProvider创建的,这里就整个都串起来了。

上面都是对
ChangeNotifierProvider进行的深入分析,我们留下几个疑问:
1、InheritedContext和updateShouldNotify是做什么的
2、 谁调用了createElement
带着问题我们开启Consumer的源码分析
4 Consumer 源码分析
Consumer和ChangeNotifierProvider是生产者和消费者模式,那生产的是什么?消费的又是什么呢?
class Consumer<T> extends SingleChildStatelessWidget {
/// {@template provider.consumer.constructor}
/// Consumes a [Provider<T>]
/// {@endtemplate}
Consumer({
Key key,
@required this.builder,
Widget child,
}) : assert(builder != null),
super(key: key, child: child);
/// {@template provider.consumer.builder}
/// Build a widget tree based on the value from a [Provider<T>].
///
/// Must not be `null`.
/// {@endtemplate}
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,
);
}
}
Consumer是一个Widget,这个没问题,我们在写的时候,就是把Consumer当成widget用的,Consumer的参数都传递到了父类SingleChildStatelessWidget,SingleChildStatelessWidget是一个抽象类,里面存储了传入的child
abstract class SingleChildStatelessWidget extends StatelessWidget
implements SingleChildWidget {
/// Creates a widget that has exactly one child widget.
const SingleChildStatelessWidget({Key key, Widget child})
: _child = child,
super(key: key);
final Widget _child;
/// A [build] method that receives an extra `child` parameter.
///
/// This method may be called with a `child` different from the parameter
/// passed to the constructor of [SingleChildStatelessWidget].
/// It may also be called again with a different `child`, without this widget
/// being recreated.
Widget buildWithChild(BuildContext context, Widget child);
@override
Widget build(BuildContext context) => buildWithChild(context, _child);
@override
SingleChildStatelessElement createElement() {
return SingleChildStatelessElement(this);
}
}
并且Consumer重写了抽象类SingleChildStatelessWidget定义的buildWithChild。
buildWithChild这个也是系统调用的方法,buildWithChild回调的时候,会接收一个child参数,这个参数可能和SingleChildStatelessWidget的构造函数传递进去的不一样,当控件没有被重新创建的时候也会再次调用并传递不同的child,大致的意思就是,不管你传进来的child是否变化,buildWithChild都可能带着新的child再次回调,buildWithChild的实现里返回的是一个builder,里面的参数value传递的是Provider.of<T>(context),这就和Provider建立起关系了,传进来的builder是用来构建一个widget tree的,这个值一定不能为null,大概理解下就是buildWithChild是用Consumer传进来的builder构建并返回一个新的Widget,使用的参数是系统回调child,但这个child我们通常没有用,最终这个builder的执行将会调用下面红色箭头处的代码。
小结:系统调用buildWithChild,buildWithChild调用builder来将widget tree变成element tree。

而传递的
model就是Provider.of<T>(context),这也就是为什么我们通常用类似下面的写法也可以得到相同的效果
class ProviderDebugPage1 extends StatelessWidget {
final String title;
ProviderDebugPage1({this.title});
@override
Widget build(BuildContext context) {
print('---provider build ---');
return Scaffold(
appBar: AppBar(
title: Text(this.title),
),
body: Column(
children: <Widget>[
Builder(
builder: (context) {
// 获取到provider提供出来的值
MyModel1 _model = Provider.of<MyModel1>(context, listen: false);
return Container(
margin: const EdgeInsets.only(top: 20),
width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.all(20),
alignment: Alignment.center,
color: Colors.lightBlueAccent,
child: Text('不监听Model1当前是:${_model.counter}'));
},
),
Consumer<MyModel1>(
// 获取到provider提供出来的值
builder: (context, model, child) {
return Container(
margin: const EdgeInsets.only(top: 20),
width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.all(20),
alignment: Alignment.center,
color: Colors.lightGreen,
child: Text('Model1当前是:${model.counter}',
),
);
},
),
Consumer<MyModel2>(
// 获取到provider提供出来的值
builder: (context, model, child) {
return FlatButton(
color: Colors.tealAccent,
onPressed:model.incrementCounter,
child: Icon(Icons.add));
},
),
);
}
}
原因就是Consumer里面封装了Provider.of,简单说就是,Consumer内置了builder的功能,并且Model对象被主动回传了。好了,是时候看一下非常重要的Provider.of<T>(context)了
class Provider<T> extends InheritedProvider<T> {
/// Creates a value, store it, and expose it to its descendants.
///
/// The value can be optionally disposed using [dispose] callback.
/// This callback which will be called when [Provider] is unmounted from the
/// widget tree.
Provider({
Key key,
@required Create<T> create,
Dispose<T> dispose,
bool lazy,
TransitionBuilder builder,
Widget child,
}) : assert(create != null),
super(
key: key,
lazy: lazy,
builder: builder,
create: create,
dispose: dispose,
debugCheckInvalidValueType: kReleaseMode
? null
: (T value) =>
Provider.debugCheckInvalidValueType?.call<T>(value),
child: child,
);
/// Expose an existing value without disposing it.
///
/// {@template provider.updateshouldnotify}
/// `updateShouldNotify` can optionally be passed to avoid unnecessarily
/// rebuilding dependents when [Provider] is rebuilt but `value` did not change.
///
/// Defaults to `(previous, next) => previous != next`.
/// See [InheritedWidget.updateShouldNotify] for more information.
/// {@endtemplate}
Provider.value({
Key key,
@required T value,
UpdateShouldNotify<T> updateShouldNotify,
TransitionBuilder builder,
Widget child,
}) : assert(() {
Provider.debugCheckInvalidValueType?.call<T>(value);
return true;
}()),
super.value(
key: key,
builder: builder,
value: value,
updateShouldNotify: updateShouldNotify,
child: child,
);
/// Obtains the nearest [Provider<T>] up its widget tree and returns its
/// value.
///
/// If [listen] is `true`, later value changes will trigger a new
/// [State.build] to widgets, and [State.didChangeDependencies] for
/// [StatefulWidget].
///
/// `listen: false` is necessary to be able to call `Provider.of` inside
/// [State.initState] or the `create` method of providers like so:
///
/// ```dart
/// Provider(
/// create: (context) {
/// return Model(Provider.of<Something>(context, listen: false)),
/// },
/// )
/// ```
static T of<T>(BuildContext context, {bool listen = true}) {
assert(context != null);
assert(
context.owner.debugBuilding ||
listen == false ||
debugIsInInheritedProviderUpdate,
'''
Tried to listen to a value exposed with provider, from outside of the widget tree.
This is likely caused by an event handler (like a button's onPressed) that called
Provider.of without passing `listen: false`.
To fix, write:
Provider.of<$T>(context, listen: false);
It is unsupported because may pointlessly rebuild the widget associated to the
event handler, when the widget tree doesn't care about the value.
The context used was: $context
''',
);
final inheritedElement = _inheritedElementOf<T>(context);
if (listen) {
context.dependOnInheritedElement(inheritedElement);
}
return inheritedElement.value;
}
static _InheritedProviderScopeElement<T> _inheritedElementOf<T>(
BuildContext context,
) {
assert(context != null, '''
Tried to call context.read/watch/select or similar on a `context` that is null.
This can happen if you used the context of a StatefulWidget and that
StatefulWidget was disposed.
''');
assert(
_debugIsSelecting == false,
'Cannot call context.read/watch/select inside the callback of a context.select',
);
assert(
T != dynamic,
'''
Tried to call Provider.of<dynamic>. This is likely a mistake and is therefore
unsupported.
If you want to expose a variable that can be anything, consider changing
`dynamic` to `Object` instead.
''',
);
_InheritedProviderScopeElement<T> inheritedElement;
if (context.widget is _InheritedProviderScope<T>) {
// An InheritedProvider<T>'s update tries to obtain a parent provider of
// the same type.
context.visitAncestorElements((parent) {
inheritedElement = parent.getElementForInheritedWidgetOfExactType<
_InheritedProviderScope<T>>() as _InheritedProviderScopeElement<T>;
return false;
});
} else {
inheritedElement = context.getElementForInheritedWidgetOfExactType<
_InheritedProviderScope<T>>() as _InheritedProviderScopeElement<T>;
}
if (inheritedElement == null) {
throw ProviderNotFoundException(T, context.widget.runtimeType);
}
return inheritedElement;
}
...下面省略debugCheckInvalidValueType方法
}
尝试翻译下,向上查找最近的一个使用Provider植入的T类型的value,简单来说就是顺着widget数查找最近的数据类型是T的数据,并返回这个数据,通常情况下,我们想要共享数据,会把数据存放在InheritedWidget中,因为Flutter 开发中,程序员只能拿到Widget,通常不会直接操作Element,但Element才是真正决定视图显示的,所以,Element通过持有Widget来间接操作数据,具体原理可以参考这篇文章。调用Provider.of<T>(context)时候有个listen参数,默认是true,会调用dependOnInheritedElement,它需要一个_inheritedElementOf参数,这里会访问当前节点的parent:context.visitAncestorElements,前提是当前widget是_InheritedProviderScope类型的,也就是数据节点,_InheritedProviderScope我们第一次提到是在说createElement方法的时候,继续看getElementForInheritedWidgetOfExactType,已经来到核心代码了
InheritedElement getElementForInheritedWidgetOfExactType<T extends InheritedWidget>() {
assert(_debugCheckStateIsActiveForAncestorLookup());
final InheritedElement ancestor = _inheritedWidgets == null ? null : _inheritedWidgets[T];
return ancestor;
}
从_inheritedWidgets取出Key为泛型T的对象的数据,那我们看看是在哪里存储的吧
class InheritedElement extends ProxyElement {
/// Creates an element that uses the given widget as its configuration.
InheritedElement(InheritedWidget widget) : super(widget);
@override
InheritedWidget get widget => super.widget as InheritedWidget;
final Map<Element, Object> _dependents = HashMap<Element, Object>();
@override
void _updateInheritance() {
assert(_active);
final Map<Type, InheritedElement> incomingWidgets = _parent?._inheritedWidgets;
if (incomingWidgets != null)
_inheritedWidgets = HashMap<Type, InheritedElement>.from(incomingWidgets);
else
_inheritedWidgets = HashMap<Type, InheritedElement>();
_inheritedWidgets[widget.runtimeType] = this;
}
下面是Element类的
void mount(Element parent, dynamic newSlot) {
assert(_debugLifecycleState == _ElementLifecycle.initial);
assert(widget != null);
assert(_parent == null);
assert(parent == null || parent._debugLifecycleState == _ElementLifecycle.active);
assert(slot == null);
assert(depth == null);
assert(!_active);
_parent = parent;
_slot = newSlot;
_depth = _parent != null ? _parent.depth + 1 : 1;
_active = true;
if (parent != null) // Only assign ownership if the parent is non-null
_owner = parent.owner;
final Key key = widget.key;
if (key is GlobalKey) {
key._register(this);
}
_updateInheritance();
assert(() {
_debugLifecycleState = _ElementLifecycle.active;
return true;
}());
void activate() {
assert(_debugLifecycleState == _ElementLifecycle.inactive);
assert(widget != null);
assert(owner != null);
assert(depth != null);
assert(!_active);
final bool hadDependencies = (_dependencies != null && _dependencies.isNotEmpty) || _hadUnsatisfiedDependencies;
_active = true;
// We unregistered our dependencies in deactivate, but never cleared the list.
// Since we're going to be reused, let's clear our list now.
_dependencies?.clear();
_hadUnsatisfiedDependencies = false;
_updateInheritance();
assert(() {
_debugLifecycleState = _ElementLifecycle.active;
return true;
}());
if (_dirty)
owner.scheduleBuildFor(this);
if (hadDependencies)
didChangeDependencies();
}
}
说明在mount和activate时候都会用,因为子类InheritedElement重写了_updateInheritance方法,所以当系统调用mount或者activate方法的时候,自然来到了InheritedElement类的实现,至于这里系统什么时机调用mount我们还是先mark下。这里有一个需要特别注意的,_inheritedWidgets这个是定义在Element类里的字典,但是字典的Key是泛型,Value是InheritedElement
Map<Type, InheritedElement> _inheritedWidgets;
在存储的时候,
_inheritedWidgets[widget.runtimeType] = this;
把自己存在了父类的_inheritedWidgets中,但如果父类对象已经存储了T类型的InheritedElement,那就直接复用这个,如果没有就创建它,简单说就是,获取parent值,并注册自身。初始化的时候将InheritedElement类的对象存储在Element类的_inheritedWidgets中,这样在获取的时候,就可以通过parent .getElementForInheritedWidgetOfExactType拿到,通过调试代码,我们发现_InheritedProviderScope没有用到,因为这些节点并不是_InheritedProviderScopeElement类型的,context类型是SingleChildStatelessElement,context.widget的类型是Consumer<T>


所以,不管是否是
_InheritedProviderScopeElement节点,都可以拿到对应的inheritedElement节点,冥冥之中,我们似乎感觉,一直被系统支配,汇总下我们的问题:
1 我们在使用
ChangeNotifierProvider的时候,最终是包装成_Delegate的子类_CreateInheritedProvider,然而createElement是谁调的
2 分析Consumer,最终在调用builder的时候使用到了系统回调context,context的类型为什么是SingleChildStatelessElement
3 在给builder传递参数的时候,使用的Provider.of<T>(context)最终是使用Element类的_inheritedWidgets存储的InheritedElement,最终应用层拿到的T实际是inheritedElement.value,那InheritedElement和T又是如何建立关系的
这一切的答案都在Element中,由于篇幅有限,我们带着这些问题,通过代码调试,在下一篇来一探究竟