Provider 源码走读(从BlocProvider开始)

1,636 阅读7分钟

本篇基于分析代码版本:

flutter_bloc: v0.21.0

provider: v3.1.0

BlocProvider

1、官方解释功能:

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.

简单说 BlocProvider 允许控件树中的子控件能够获取到同一个 bloc 实例。

BlocProvider示意图

2、使用方法

// Father Widget
BlocProvider(
  builder: (BuildContext context) => BlocA(),
  child: ChildA(), 
);

// Child Widget
var blocA = BlocProvider.of<BlocA>(context);

3、代码走读:构造函数

首先看下 BlocProvider 的构造函数。

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

上面代码里去掉了注释,而注释对构造函数的功能有两个信息点:

  • 使用 ValueBuilder 构建 bloc 并提供给子节点获取。

  • 自动处理了 bloc 的 dispose 工作。

所以我们有了两个疑问:

1、BlocProvider 如何能够提供给子节点提供 bloc ?

2、如何保障 bloc 单一实例,且能自动处理 bloc 的 dispose ?

答案需要从 BlocProvider 的父类 Provider 里寻找。

Provider

provider

1、先看问题二:如何保障 bloc 单一实例,且能自动处理 bloc 的 dispose ?

答案在 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,
        );

  • 第 9 行,构造函数里实现了一个 bloc dispose 的方法,并作为父类构造函数的参数传入。

[./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 代理内部细节,我们过会儿回来看。


2、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

  • 代码第 22、52 行,分别调用了代理 delegateinitDelegate() 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 里就有答案。


3、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 方法。

  • 代码 17、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;
}
  • 其父类 ValueDelegate,内容比较简单,扩展 StateDelegate 并增加存储了 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() {}
}
  • 其父类 StateDelegate ,剔除注释后比较直观了,就是一个 State 生命周期回调的代理包装。

小结:

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 及其父类的构造函数看下来就比较清楚了。


4、再看问题一:如何存储这个单一实例 bloc,并提供给子控件的?

// 子控件是如何通过下面这句获取到 bloc 的 ?

var blocA = BlocProvider.of(context);

从上面的第 3 节,我们知道代理里面有我们的且唯一的 bloc,存储形式就是 _value

而 BlocProvider 继承自 Provider,最终都是一个 StatefulWidget,我们看看它的 build 方法有什么特别的。

4-1、Provider 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 传入的 valueBuilderdispose() 方法。

  • 第 9 行,child 就是控件 BlocProvider 传入的 child widget 。


4-2、InheritedProvider

[./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 。


4-3、BlocProvider.of(context)

[./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)而已。

本篇总结

至此我们应该搞明白了以下几点:

1、BlocProvider 构造函数传入的参数被父类 Provider 控件包装成代理 BuilderStateDelegate。而 Provider 本质是一个 StatefulWidget 控件,在其 State 的生命周期里,触发代理的相对应回调。

2、BuilderStateDelegate 代理可以感知 StatefulWidget 的生命周期,在适当时候,创建、保存和销毁唯一的 _value值(就是我们的 bloc)。

3、Provider 在 build() 方法里,返回了一个 InheritedProvider,传入了代理的 _value值。 它本质是 InheitedWidget 类型的控件。

4、通过 BlocProvider.of(context) 获取到 bloc ,其实是通过 context.ancestorInheritedElementForWidgetOfExactType(type) 获取到 InheritedProvider,取出里面的 _value值。

现在回过来看这几个控件的继承关系图,是不是更清楚了呢?

provider

备注:

1、RepositoryProvider 代码类似,不再赘述。

2、context.ancestorInheritedElementForWidgetOfExactType(type) 如何获取到 type 类型的 widget ?( Map<Type, InheritedElement> _inheritedWidgets 缓存 ) 后续再讲。