本篇基于分析代码版本:缓存
flutter_bloc: v0.21.0markdown
provider: v3.1.0框架
It is used as a dependency injection (DI) widget so that a single instance of a bloc can be provided to multiple widgets within a subtree.ide
简单说 BlocProvider
容许控件树中的子控件可以获取到同一个 bloc
实例。函数
// Father Widget
BlocProvider(
builder: (BuildContext context) => BlocA(),
child: ChildA(),
);
// Child Widget
var blocA = BlocProvider.of<BlocA>(context);
复制代码
首先看下 BlocProvider
的构造函数。ui
class BlocProvider<T extends Bloc<dynamic, dynamic>> extends Provider<T> {
BlocProvider({
Key key,
@required ValueBuilder<T> builder,
Widget child,
}) : super(
key: key,
builder: builder,
dispose: (_, bloc) => bloc?.dispose(),
child: child,
);
复制代码
上面代码里去掉了注释,而注释对构造函数的功能有两个信息点:this
使用 ValueBuilder
构建 bloc 并提供给子节点获取。spa
自动处理了 bloc 的 dispose
工做。3d
因此咱们有了两个疑问:代理
一、BlocProvider 如何可以提供给子节点提供 bloc ?
二、如何保障 bloc 单一实例,且能自动处理 bloc 的 dispose ?
答案须要从 BlocProvider
的父类 Provider
里寻找。
答案在 BlocProvider
的父类 Provider
里,咱们看下代码
[./BlocProvider.dart]
class BlocProvider<T extends Bloc<dynamic, dynamic>> extends Provider<T> {
BlocProvider({
Key key,
@required ValueBuilder<T> builder,
Widget child,
}) : super(
key: key,
builder: builder,
dispose: (_, bloc) => bloc?.dispose(),
child: child,
);
复制代码
[./provider.dart]
class Provider<T> extends ValueDelegateWidget<T> implements SingleChildCloneableWidget {
Provider({
Key key,
@required ValueBuilder<T> builder,
Disposer<T> dispose,
Widget child,
}) : this._(
key: key,
delegate: BuilderStateDelegate<T>(builder, dispose: dispose),
updateShouldNotify: null,
child: child,
);
Provider._({
Key key,
@required ValueStateDelegate<T> delegate,
this.updateShouldNotify,
this.child,
}) : super(key: key, delegate: delegate);
}
复制代码
BlocProvider(builder, child)
调用父类 Provider 的公开构造函数,再重定向到私有构造函数。
第 10 行,将 BlocProvider 传入的 bulder、dispose 方法包装成 BuilderStateDelegate 代理对象。
第 20 行,将这个代理做为参数传入父类 ValueDelegateWidget 的构造函数。
这里的
BuilderStateDelegate
代理内部细节,咱们过会儿回来看。
继续追溯父类,看看是如何使用这个代理 BuilderStateDelegate
的。
[/delegate_widget.dart]
abstract class ValueDelegateWidget<T> extends DelegateWidget {
ValueDelegateWidget({
Key key,
@required ValueStateDelegate<T> delegate,
}) : super(key: key, delegate: delegate);
@override
@protected
ValueStateDelegate<T> get delegate => super.delegate as ValueStateDelegate<T>;
}
复制代码
Provider 的父类是个抽象类 ValueDelegateWidget 代码很简单,支持使用的代理类型只有 ValueStateDelegate 。
上一小节遗留的 BuilderStateDelegate 就是一种 ValueStateDelegate 的具体实现类。
[/delegate_widget.dart]
abstract class DelegateWidget extends StatefulWidget {
const DelegateWidget({
Key key,
this.delegate,
}) : assert(delegate != null),
super(key: key);
@protected
final StateDelegate delegate;
//...省略
@override
_DelegateWidgetState createState() => _DelegateWidgetState();
}
class _DelegateWidgetState extends State<DelegateWidget> {
@override
void initState() {
super.initState();
_mountDelegate();
_initDelegate();
}
void _initDelegate() {
// ... 省略断言
widget.delegate.initDelegate();
}
void _mountDelegate() {
widget.delegate
.._context = context
.._setState = setState;
}
void _unmountDelegate(StateDelegate delegate) {
delegate
.._context = null
.._setState = null;
}
@override
void didUpdateWidget(DelegateWidget oldWidget) {
// ... 省略
}
@override
Widget build(BuildContext context) => widget.build(context);
@override
void dispose() {
widget.delegate.dispose();
_unmountDelegate(widget.delegate);
super.dispose();
}
}
复制代码
DelegateWidget 就是一个 StatefulWidget 控件,代码第 9 行,存储了构造方法传进来的代理 delegate
。 而这个代理就是 Provider 里的 BuilderStateDelegate
。
代码第 2二、52 行,分别调用了代理 delegate
的 initDelegate()
dispose()
方法建立和销毁 bloc。
小结下:
2-1. BlocProvider 构造函数参数一路传递的路径以下:
起始:
BlocProvider
(ValueBuilder
+Disposer
)-->
Provider
(BuilderStateDelegate
)-->
ValueDelegateWidget
(ValueStateDelegate
)-->
DelegateWidget
(StateDelegate
) 成为一个 StatefulWidget 的成员变量 delegate
2-2. BlocProvider 最终是继承子一个 StatefulWidget, 并经过 Provider 生成一个 BuilderStateDelegate,最后传入 delegateWidget。
2-3. 在这个 delegateWidget 的生命周期里调用代理的初始化、更新、销毁方法。
那具体到 BlocProvider 的 bloc 什么时候建立和销毁呢 ?
回到这个代理 BuilderStateDelegate 里就有答案。
[/delegate_widget.dart]
class BuilderStateDelegate<T> extends ValueStateDelegate<T> {
/// The parameter `builder` must not be `null`.
BuilderStateDelegate(this._builder, {Disposer<T> dispose})
: assert(_builder != null),
_dispose = dispose;
final ValueBuilder<T> _builder;
final Disposer<T> _dispose;
T _value;
@override
T get value => _value;
@override
void initDelegate() {
super.initDelegate();
_value = _builder(context);
}
@override
void didUpdateDelegate(BuilderStateDelegate<T> old) {
super.didUpdateDelegate(old);
_value = old.value;
}
@override
void dispose() {
_dispose?.call(context, value);
super.dispose();
}
}
复制代码
代码第 3 行,接收来自 BlocProvider 传递过来的 ValueBuilder (用来建立 bloc 的一个方法对象)和 Disposer (用来销毁 bloc 的一个方法对象)。
代码 11~12 行,存储类型为 T 的 _value
值,并提供 get 方法。
代码 1七、28 行,分别在 initDelegate()
和 dispose()
里,触发传进来的 _builder
和 _dispose
方法,初始化了 _value
值(建立 bloc)、调用了 disposer 方法(销毁 bloc)。
abstract class ValueStateDelegate<T> extends StateDelegate {
/// The member [value] should not be mutated directly.
T get value;
}
复制代码
[/delegate_widget.dart]
abstract class StateDelegate {
BuildContext _context;
BuildContext get context => _context;
StateSetter _setState;
@protected
StateSetter get setState => _setState;
@protected
@mustCallSuper
void initDelegate() {}
@protected
@mustCallSuper
void didUpdateDelegate(covariant StateDelegate old) {}
@protected
@mustCallSuper
void dispose() {}
}
复制代码
小结:
BlocProvider(
builder: (BuildContext context) => BlocA(),
child: ChildA(),
);
复制代码
3-1. 父类 Provider 里用 BuilderStateDelegate 代理包装了 bloc 的初始化和销毁方法。
3-2. BuilderStateDelegate 代理存储了(_value)bloc 初始化方法的结果
3-3. Provider 最终继承自 DelegateWidget,一个 StatefulWidget。在生命周期里调用代理的一样的方法。
3-4. 框架里常见的代理模式,顺着 BlocProvider 及其父类的构造函数看下来就比较清楚了。
// 子控件是如何经过下面这句获取到 bloc 的 ?
var blocA = BlocProvider.of(context);
从上面的第 3 节,咱们知道代理里面有咱们的且惟一的 bloc,存储形式就是 _value
。
而 BlocProvider 继承自 Provider,最终都是一个 StatefulWidget,咱们看看它的 build 方法有什么特别的。
class Provider<T> extends ValueDelegateWidget<T> implements SingleChildCloneableWidget {
@override
Widget build(BuildContext context) {
//...省略断言
return InheritedProvider<T>(
value: delegate.value,
updateShouldNotify: updateShouldNotify,
child: child,
);
}
复制代码
第 6 行,最终 build()
方法里返回的是 InheritedProvider<T>
第 7 行,给定的 value
就是代理 delegate
的 value。
而 delegate
代理就是在构造函数建立的 BuilderStateDelegate
,包装了 BlocProvider
传入的 valueBuilder
和 dispose()
方法。
第 9 行,child
就是控件 BlocProvider
传入的 child widget 。
[./provider.dart]
class InheritedProvider<T> extends InheritedWidget {
const InheritedProvider({
Key key,
@required T value,
UpdateShouldNotify<T> updateShouldNotify,
Widget child,
}) : _value = value,
_updateShouldNotify = updateShouldNotify,
super(key: key, child: child);
final T _value;
final UpdateShouldNotify<T> _updateShouldNotify;
// ... 省略
}
复制代码
InheritedProvider 其实就是一个 InheritedWidget 。
构造函数传入代理的值(delegate.value), 也被暂存为成员变量 _value 。
[./bloc_provider.dart]
// BlocProvider.of<T>() 方法
static T of<T extends Bloc<dynamic, dynamic>>(BuildContext context) {
try {
return Provider.of<T>(context, listen: false);
} catch (_) {
// ...
}
复制代码
BlocProvider.of<T>
其实调用的是 Provider 的 Provider.of<T>
方法 (listen 值为 false)。[./provider.dart]
/// Returns the type [T].
Type _typeOf<T>() => T;
// Provider.of<T>() 方法
static T of<T>(BuildContext context, {bool listen = true}) {
// this is required to get generic Type
final type = _typeOf<InheritedProvider<T>>();
final provider = listen
? context.inheritFromWidgetOfExactType(type) as InheritedProvider<T>
: context.ancestorInheritedElementForWidgetOfExactType(type)?.widget
as InheritedProvider<T>;
// ... 省略异常检查
return provider._value;
}
复制代码
代码第 8-11 行,listen 值为false,触发 context.ancestorInheritedElementForWidgetOfExactType(type)
方法找到 InheritedProvider<T>
类型的控件。
代码第 15 行,返回这个 InheritedProvider._value
联系 4-2 小节,这个返回的就是 delegate.value
, 也就是咱们在代理里生成的 bloc 了。
by flutter_bloc 做者
为何要用 ancestorInheritedElementForWidgetOfExactType 而不用 inheritFromWidgetOfExactType ?
由于 inheritFromWidgetOfExactType 不只查找获取符合指定类型的Widget,还将context 注册到该Widget,以便Widget发生变更后,context能够获取到新值;
这并非咱们想要的,咱们想要的仅仅就是符合指定类型的Widget(也就是 BlocProvider)而已。
至此咱们应该搞明白了如下几点:
一、BlocProvider 构造函数传入的参数被父类 Provider 控件包装成代理 BuilderStateDelegate。而 Provider 本质是一个 StatefulWidget 控件,在其 State 的生命周期里,触发代理的相对应回调。
二、BuilderStateDelegate 代理能够感知 StatefulWidget 的生命周期,在适当时候,建立、保存和销毁惟一的 _value
值(就是咱们的 bloc)。
三、Provider 在 build() 方法里,返回了一个 InheritedProvider,传入了代理的 _value
值。 它本质是 InheitedWidget 类型的控件。
四、经过 BlocProvider.of(context) 获取到 bloc ,实际上是经过 context.ancestorInheritedElementForWidgetOfExactType(type) 获取到 InheritedProvider,取出里面的 _value
值。
如今回过来看这几个控件的继承关系图,是否是更清楚了呢?
备注:
一、RepositoryProvider 代码相似,再也不赘述。
二、context.ancestorInheritedElementForWidgetOfExactType(type) 如何获取到 type 类型的 widget ?( Map<Type, InheritedElement> _inheritedWidgets 缓存 ) 后续再讲。