Flutter Provider源码分析

Posted 一叶飘舟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter Provider源码分析相关的知识,希望对你有一定的参考价值。

前言

 

阅读此文的彦祖,亦菲们,附送一枚Provider模板代码生成插件!

我为啥要写这个插件呢?

此事说来话短,我这不准备写解析Provider源码的文章,肯定要写这框架的使用样例啊,然后再哔哔源码呀!在写demo样例的时候,新建那俩三个文件、文件夹和必写的模板代码,这让我感到很方啊,这不耽误我时间嘛!然后就撸了这个插件,相对而言,多花了几百倍的时间。。。

希望这个插件,能减轻使用Provider小伙们的一点工作量;插件里面的模板代码是经过我深思熟虑过的,如果各位靓仔有更好的模板代码,请在评论里贴出来,我觉得合理的话,会加入到插件里。

关于Provider的源码,如果对设计模式或面向接口编程不熟悉的话,看起来是相当懵逼的,基本就是:懵逼树上懵逼果,懵逼树下你和我;Provider源码使用了大量的抽象类,调用父类构造函数,继承实现断言,很多关键的函数调用,点进去都是抽象类,必须返回好几层去看看这个抽象类的实现类是什么,看的十分头大!这里面有很多设计模式的痕迹:观察者模式、策略模式、外观模式、命令模式、访问者模式、模板模式、迭代器模式、、、

我会竭尽所能的将总体流程说清楚,相关晦涩流程会结合图文,并给出相应小demo演示

ε=(´ο`*)))唉,这篇文章写完,我感觉整个人都被掏空了。。。

不管你用或不用Provider,我相信在你读完本文的刷新机制栏目,大概率会对该框架中闪耀的智慧,感到由衷的赞叹!

使用

老规矩,说原理之前,先来看下使用

Provider的使用,和我前俩篇写的Handler和ThreadLocal使用有一些区别

Provider是一个状态管理框架,写它的使用可能会占较多篇幅,所以文章整体篇幅也会较长,请见谅。。。

我实在不想分篇幅水赞啊,而且也是为了方便大家可以在一篇文章里面查阅相关知识(请结合掘金旁边的大纲食用),也方便我随时修改优化文章内容。。。

插件

  • 插件github:provider_template
    • 使用中碰见什么bug,希望大家能及时给我提issue
  • 插件可以进入android Studio的Setting里面,选择Plugins,然后搜索flutter provider,第一个,看图上红框标定的就是了,点击install安装即可

  • 来下看使用效果图

 

  • 如果你不喜欢这种命名方式,这里提供修改入口;也支持了持久化
    • 大家按需修改吧

  • Alt + Enter : 可以选择包裹Widget,有三种可选(Consumer、Selector、ChangeNotifierProvider),一键生成麻烦,重复且使用频率很高的Widget!

  • 快捷代码片段提示:我自己写了三个,如果老哥们还有其它的骚操作,需要各位提PR啊
    • 在这个文件里面添加就行了,大家可以参照写法:provider_template
    • 输入  provider 前缀便有提示

 

写法

ChangeNotifierProvider中为什么用builder?而不用child?

  • Provider.of(context, listen: false)中的context,必须是ChangeNotifierProvider或其子Widget的
  • 使用ProEasyCounterPage的context,会发现无法找到ProEasyCounterProvider的情况,导致无法触发increment()方法
  • 原理是什么?看完文章,你就造了
class ProEasyCounterPage extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return ChangeNotifierProvider(
      create: (BuildContext context) => ProEasyCounterProvider(),
      builder: (context, child) => _buildPage(context),
    );
  

  Widget _buildPage(BuildContext context) 
    final provider = context.read<ProEasyCounterProvider>();
	
    return Scaffold(
      appBar: AppBar(title: Text('Provider-Easy范例')),
      body: Center(
        child: Consumer<ProEasyCounterProvider>(
          builder: (context, provider, child) 
            return Text(
              '点击了 $provider.count 次',
              style: TextStyle(fontSize: 30.0),
            );
          ,
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => provider.increment(),
        child: Icon(Icons.add),
      ),
    );
  


class ProEasyCounterProvider extends ChangeNotifier 
  int count = 0;

  void increment() 
    count++;
    notifyListeners();
  

复制代码

获取注入的实例的方法有点长;所以我在 _buildPage(...) 这个方法中,将其提出来,单独赋值给了一个变量,方便后续使用

插件生成代码

插件生成代码分为俩个模式:Default和High

默认模式有俩个文件(Default):view、provider

高级模式有三个文件(High):view、provider、state

大家都是用Flutter的老手,对这种结构应该非常了解,state层是把数据层独立出来维护

在非常复杂的提交界面,state层我甚至还会分出:跳转(jump)、提交(submit)、展示(show)这三种结构;没办法,一个模块搞了上百个变量,不这样分,太难维护了

default:默认模式下的模板代码

  • view
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import 'provider.dart';

class CounterPage extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return ChangeNotifierProvider(
      create: (BuildContext context) => CounterProvider(),
      builder: (context, child) => _buildPage(context),
    );
  

  Widget _buildPage(BuildContext context) 
    final provider = context.read<CounterProvider>();

    return Container();
  

复制代码
  • provider
import 'package:flutter/material.dart';

class CounterProvider extends ChangeNotifier 


复制代码

High:高级模式下的模板代码

  • view
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import 'provider.dart';

class CounterPage extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return ChangeNotifierProvider(
      create: (BuildContext context) => CounterProvider(),
      builder: (context, child) => _buildPage(context),
    );
  

  Widget _buildPage(BuildContext context) 
    final provider = context.read<CounterProvider>();
	final state = provider.state;
     
    return Container();
  

复制代码
  • provider
import 'package:flutter/material.dart';

import 'state.dart';

class CounterProvider extends ChangeNotifier 
  final state = CounterState();

复制代码
  • state
class CounterState 

  CounterState() 
    // init some variables
  

复制代码

前置知识

下面就是Provider的源码分析内容了,如果大家赶时间,可以点个赞(方便日后查阅,滑稽.jpg),回头等有时间,再静下心来慢慢看;我怕你快餐式阅读,读到刷新机制那块,会直接骂街,这写的啥玩意???

Provider的刷新机制,相关流程相当之绕,我已经竭尽全力,精简了无数我们不需要关注的代码,然后一步步带着你的思路去走一遍正确的流程,相关类还给了很多说明,但是架不住源码流程山路十八弯,绕的一比啊!你如果不用心去看,去体会,会相当烦躁。。。

我已经帮大家熬过最蛋筒的部分,相关绕的流程画了详细的图示,我已经努力了;如果你想知道Provider内部运转机制,现在就需要你努力了!

ChangeNotifier的单独使用

ValueListenableBuilder和ValueNotifier可以配套使用,ValueListenableBuilder内部也是一个StatefulWidget,代码很简单,感兴趣的可以自己查看

这个暂且不表,这边就搞最原始的ChangeNotifier的使用

大家肯定在Provider都写过继承ChangeNotifier的代码,而且写的非常多,但是大家知道怎么单独使用ChangeNotifier,以达到控制界面变化的效果吗?

我搜了很多怎么单独使用ChangeNotifier的文章,但是基本都是写配合ChangeNotifierProvider在Provider中使用的,我佛了呀,搜到寥寥无几的文章,也没说清楚,怎么单独使用;我想这玩意是不是有个单独XxxWidgetBuild配合使用?但是!我怎么都找不到,气抖冷!

我突然想到,TextField控件中的TextEditingController用到了ChangeNotifier,总不可能TextField还用Provider吧!我在源码里面一通翻,各种super,abstract,私有变量,看的头皮发麻,最后终于找到了关键代码,搞清楚TextField是怎么使用ChangeNotifier的了,为什么每次改变TextEditingController的text值,然后在TextField数据框里的数据也及时改变了,其实最后还是用到setState

TextField中的流程代码不贴了,如果贴出来,会相当占篇幅:我下面会写一个颗粒度最小ChangeNotifier的单独使用demo

  • TextEditingController实际是继承了ValueNotifier,来看下ValueNotifier
class ValueNotifier<T> extends ChangeNotifier implements ValueListenable<T> 
  ValueNotifier(this._value);
  @override
  T get value => _value;
  T _value;
  set value(T newValue) 
    if (_value == newValue)
      return;
    _value = newValue;
    notifyListeners();
  

  @override
  String toString() => '$describeIdentity(this)($value)';

复制代码

ValueNotifier实际是对ChangeNotifier的封装

这里影响不大,我们还是使用ChangeNotifier,来写一个类似TextField中的控制器效果,每当控制器中的数值改变,其控件内容就自动更新

  • 先使用ChangeNotifier搞一个控制器
class TestNotifierController extends ChangeNotifier 
  String _value = '0';

  String get value => _value;

  set value(String newValue) 
    if (_value == newValue) return;
    _value = newValue;
    notifyListeners();
  

复制代码
  • 搭配这个控制器的Widget
    • OK,这样就搞定了,改变控制器的数据,Widget也会自动刷新
    • 我把功能颗粒度压缩的非常小,希望大家阅读会比较轻松
class TestNotifierWidget extends StatefulWidget 
  const TestNotifierWidget(
    Key? key,
    this.controller,
  ) : super(key: key);

  final TestNotifierController? controller;

  @override
  _TestNotifierState createState() => _TestNotifierState();


class _TestNotifierState extends State<TestNotifierWidget> 
  @override
  void initState() 
    ///添加回调 value改变时,自动触发回调内容
    widget.controller?.addListener(_change);
    super.initState();
  

  @override
  Widget build(BuildContext context) 
    return Text(
      widget.controller?.value ?? '初始值为空',
      style: TextStyle(fontSize: 30.0),
    );
  

  ///被触发的回调
  void _change() 
    setState(() );
  

复制代码
  • 来看下怎么使用这个控件
    • 使用代码已经非常简单了:onPressed改变了控制器数值内容,TestNotifierWidget控件会自动刷新
class TestNotifierPage extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    final controller = TestNotifierController();
    var count = 0;

    return Scaffold(
      appBar: AppBar(title: Text('ChangeNotifier使用演示')),
      body: Center(
        child: TestNotifierWidget(controller: controller),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () 
          controller.value = '数值变化:$(++count).toString()';
        ,
        child: Icon(Icons.add),
      ),
    );
  

复制代码
  • 来看下效果图

  

Function Call()

这里说个小知识点,源码里面大量使用了这个技巧,网上搜了下,很少提到这个的,这边记一笔

每个Function都有个Call()方法

  • 下面俩种方式调用是等同的,都能调用test方法
void main()
    test();

    test.call();


void test()
    print('test');

复制代码

你可能想,这有什么用,我还多写一个 .call ?

来看下一个小范例,就知道这个东西能帮我们简化很多代码

  • 平时封装带有CallBack回调Widget
    • 这边写了俩个自定义的点击回调判断操作
    • 如果不做判空操作,外部未实现这个Function,点击事件会报空异常
class TestWidget extends StatelessWidget 
  const TestWidget(
    Key? key,
    this.onTap,
    this.onBack,
  ) : super(key: key);

  final VoidCallback? onTap;

  final VoidCallback? onBack;

  @override
  Widget build(BuildContext context) 
    return GestureDetector(
      onTap: () 
        if (onTap != null) 
          onTap!();
        
        if (onBack != null) 
          onBack!();
        
      ,
      child: Container(),
    );
  

复制代码
  • 使用 .call() 后,可以怎么写呢?
    • 可以干掉麻烦的if判空操作了!
class TestWidget extends StatelessWidget 
  const TestWidget(
    Key? key,
    this.onTap,
    this.onBack,
  ) : super(key: key);

  final VoidCallback? onTap;

  final VoidCallback? onBack;

  @override
  Widget build(BuildContext context) 
    return GestureDetector(
      onTap: () 
        onTap?.call();
        onBack?.call();
      ,
      child: Container(),
    );
  

复制代码

刷新机制

Provider的刷新机制是非常重要的,只要把Provider的刷新机制搞清楚,这个框架在你面前,将不在神秘!

实际上,大家只要看到ChangeNotifier的应用,那肯定知道,这就是个观察者模式,但是问题是:它的监听在何处添加?添加的监听逻辑是否有完整的初始化链路?监听逻辑是什么?为什么触发监听逻辑,能导致相应控件刷新?

  • 上面初始化的完整链路看的真是有点蛋痛
    • 源码东一榔锤西一棒的,而且还用了大量了抽象类,想直接定位逻辑,那是不可能的,你必须找到实现类赋值的地方,才能明白内部运转
    • 不搞清楚完整初始化链路,内心就相当于膈应,明知道他肯定初始化了,却不知道他在哪初始化的,就很难受
    • 我下面将相关流程理了一遍,希望对大家有所帮助
  • 要读懂Provider,必须要有个前提,明白什么观察者模式:观察者模式其实很简单,简单描述下
    • 定义个List类型,泛型为一个抽象类,初始化这个List
    • 然后给这个List,add这个抽象类的实现类实例
    • 某个合适时候,遍历这个List所有实例,触发所有实例的某个方法
    • 如果将这个思想和反射注解结合在一起,就能大大拓宽它的使用面,例如android里的EventBus。。。

总流程

继承ChangeNotifier的类,是通过ChangeNotifierProvider传入到Provider内部,很明显ChangeNotifierProvider这个类很重要,基本可以算是框架的主入口

这边梳理下ChangeNotifierProvider 回溯的总流程,其它的旁枝末节,暂时不贴代码,这个往上回溯的过程,实例了一个很重要的上下文类,很多关键的类初始化都和这个上下文类有关系,先来回溯下这个重要的流程!

  • ChangeNotifierProvider
    • 这地方有个_dispose回调,是定义好的,内部逻辑是回收ChangeNotifier实例
    • 这里将该方法赋值给了他的父类ListenableProvider,然后一层层往上回溯
class ChangeNotifierProvider<T extends ChangeNotifier?> extends ListenableProvider<T> 
  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,
        );

  ...

  static void _dispose(BuildContext context, ChangeNotifier? notifier) 
    notifier?.dispose();
  

复制代码
  • ListenableProvider
    • 这地方有个_startListening回调,这个方法极其重要
class ListenableProvider<T extends Listenable?> extends InheritedProvider<T> 
  ListenableProvider(
    Key? key,
    required Create<T> create,
    Dispose<T>? dispose,
    bool? lazy,
    TransitionBuilder? builder,
    Widget? child,
  ) : super(
          key: key,
          startListening: _startListening,
          create: create,
          dispose: dispose,
          lazy: lazy,
          builder: builder,
          child: child,
        );  

  ...

  static VoidCallback _startListening(InheritedContext e, Listenable? value,) 
    value?.addListener(e.markNeedsNotifyDependents);
    return () => value?.removeListener(e.markNeedsNotifyDependents);
  

复制代码
  • InheritedProvider
    • 这个类就是逻辑的纠缠点了:我省略了大量和主流程无关的代码,不然会十分影响你的关注点,会很难受
    • 这里就不需要看他的父类了,他的父类是SingleChildStatelessWidget,这个类是对StatelessWidget类的一个封装,能稍微优化下嵌套问题,无关紧要
    • 需要看下buildWithChild(看成StatelessWidget的build方法就行了)方法里面的_InheritedProviderScope类,来看下他的源码
class InheritedProvider<T> extends SingleChildStatelessWidget 
  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);

  ...

  final _Delegate<T> _delegate;
  final bool? _lazy;
  final TransitionBuilder? builder;

  ...

  @override
  Widget buildWithChild(BuildContext context, Widget? child) 
    ...
    return _InheritedProviderScope<T>(
      owner: this,
      debugType: kDebugMode ? '$runtimeType' : '',
      child: builder != null
          ? Builder(
              builder: (context) => builder!(context, child),
            )
          : child!,
    );
  

复制代码
  • _InheritedProviderScope
    • 这里是继承了InheritedWidget,里面重写createElement方法,在构建Widget的时候,这个方法是肯定会被调用的!
    • 马上就要到最重要的类了,就是createElement中实例化的_InheritedProviderScopeElement类!
class _InheritedProviderScope<T> extends InheritedWidget 
  const _InheritedProviderScope(
    required this.owner,
    required this.debugType,
    required Widget child,
  ) : super(child: child);

  final InheritedProvider<T> owner;
  final String debugType;

  @override
  bool updateShouldNotify(InheritedWidget oldWidget) 
    return false;
  

  @override
  _InheritedProviderScopeElement<T> createElement() 
    return _InheritedProviderScopeElement<T>(this);
  

复制代码
  • _InheritedProviderScopeElement:实现方法里面的逻辑全省略了,逻辑太多,看着头晕
    • 先说明下,这个类是极其极其重要的!大家可以看下他实现了一个什么抽象类:InheritedContext!
    • InheritedContext继承了BuildContext,也就是说,这里作者实现了BuildContext所有抽象方法
      • 是的,BuildContext也是个抽象类,我们可以去实现多个不同实现类
      • 内部系统只需要特定的周期去触发相应方法,就可以了
      • 你可以在相应的方法里面实现自己的逻辑,大大的扩展了逻辑,怎么说呢?有点策略模式味道,可以动态替换实现类
    • _InheritedProviderScopeElement算是实现了:InheritedContext和BuildContext;BuildContext中有很多方法是和控件生命周期挂钩的,例如热重载触发(reassemble),setState触发(build、performRebuild)、以及很有意思的强制依赖项组件刷新(markNeedsNotifyDependents:这是Provider作者在InheritedContext中抽象的方法)。。。
abstract class InheritedContext<T> extends BuildContext 
  T get value;

  void markNeedsNotifyDependents();

  bool get hasValue;


class _InheritedProviderScopeElement<T> extends InheritedElement implements InheritedContext<T> 
  _InheritedProviderScopeElement(_InheritedProviderScope<T> widget)
      : super(widget);

  ...

  @override
  void mount(Element? parent, dynamic newSlot) 
    ...
  

  @override
  _InheritedProviderScope<T> get widget => super.widget as _InheritedProviderScope<T>;

  @override
  void reassemble() 
    ...
  

  @override
  void updateDependencies(Element dependent, Object? aspect) 
    ...
  

  @override
  void notifyDependent(InheritedWidget oldWidget, Element dependent) 
    ...
  

  @override
  void performRebuild() 
    ...
  

  @override
  void update(_InheritedProviderScope<T> newWidget) 
    ...
  

  @override
  void updated(InheritedWidget oldWidget) 
    ...
  

  @override
  void didChangeDependencies() 
    ...
  

  @override
  Widget build() 
    ...
  

  @override
  void unmount() 
    ...
  

  @override
  bool get hasValue => _delegateState.hasValue;

  @override
  void markNeedsNotifyDependents() 
    ...
  

  bool _debugSetInheritedLock(bool value) 
    ...
  

  @override
  T get value => _delegateState.value;

  @override
  InheritedWidget dependOnInheritedElement(
    InheritedElement ancestor, 
    Object? aspect,
  ) 
    ...
  

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) 
    ...
  

复制代码

上面进行了五步的回溯流程,如果不仔细看清楚相关类里面的逻辑,很可能就迷失在super方法里。。。

通过上面的五步回溯,我们可以断定一个事实:_InheritedProviderScopeElement(实现BuildContext) 被实例化了,而且他在初始化的时候被调用了,对应的,其内部相应的周期也能被正常触发!这样之前看源码困扰我的很多问题,就迎刃而解了!

  • 图示
    • 上面回溯的层级过多,还有很多的继承和实现
    • 看了后,脑中可能没啥印象,所以此处画了流程图,可以参照对比

添加监听

整个刷新机制里面有个相当重要的一环,我们从Create中传入的类,它内部是怎么处理的?

class ProEasyCounterPage extends StatelessWidget 
  final provider = ProEasyCounterProvider();

  @override
  Widget build(BuildContext context) 
    return ChangeNotifierProvider(
      create: (BuildContext context) => provider,
      child: Container(),
    );
  

复制代码

就算没看源码,我也能断定传入的XxxProvider实例,肯定使用了其本身的addListener方法!

但是找这个addListener方法,实在让我找自闭了,之前因为没梳理总流程,对其初始化链路不明晰,找到了addListener方法,我都十分怀疑,是不是找对了、其它地方是不是还有addListener方法;后来没办法,就把Provider源码下载下来(之前直接项目里面点Provider插件源码看的),全局搜索addListener方法,排除所有的测试类中使用的,然后断定我找对了,整个添加监听的链路是通顺的!

下面来整体的带大家过一遍源码

靓仔们,我要开始绕了!!!

流转

  • ChangeNotifierProvider
    • 明确下Create是一个Function,返回继承ChangeNotifier类的实例
    • 这里一定要记住create这个变量的走向,其中的T就是继承ChangeNotifier类的关键类
    • 增加了_dispose方法,传给了父类
    • create这里super给其父类,回溯下父类
typedef Create<T> = T Function(BuildContext context);

class ChangeNotifierProvider<T extends ChangeNotifier?> extends ListenableProvider<T> 
  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,
        );

  ...

  static void _dispose(BuildContext context, ChangeNotifier? notifier) 
    notifier?.dispose();
  

复制代码
  • ListenableProvider
    • 此处将create实例super给了父类
    • 还增加一个_startListening方法,也同样给了父类
class ListenableProvider<T extends Listenable?> extends InheritedProvider<T> 
  ListenableProvider(
    Key? key,
    required Create<T> create,
    Dispose<T>? dispose,
    bool? lazy,
    TransitionBuilder? builder,
    Widget? child,
  ) : super(
          key: key,
          startListening: _startListening,
          create: create,
          dispose: dispose,
          lazy: lazy,
          builder: builder,
          child: child,
        );

  ...

  static VoidCallback _startListening(InheritedContext e, Listenable? value,) 
    value?.addListener(e.markNeedsNotifyDependents);
    return () => value?.removeListener(e.markNeedsNotifyDependents);
  

复制代码
  • InheritedProvider
    • 这地方和上面总流程不太一样了
    • create、dispose、startListening传给了_CreateInheritedProvider
    • 需要看下_CreateInheritedProvider
class InheritedProvider<T> extends SingleChildStatelessWidget 
  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);

  ...

复制代码
  • 流程图示

_CreateInheritedProvider

这地方会进行一个很重要的回溯流程,回溯到_InheritedProviderScopeElement

下次再有需要用到这个类,就直接拿这个类来讲了

  • _CreateInheritedProvider说明
    • _CreateInheritedProvider继承了抽象类 _Delegate,实现了其createState抽象方法
    • 按理说,主要逻辑肯定在createState方法中  _CreateInheritedProviderState 实例中
    • 必须要看下_CreateInheritedProvider实例,在何处调用 createState方法,然后才能继续看 _CreateInheritedProviderState的逻辑
@immutable
abstract class _Delegate<T> 
  _DelegateState<T, _Delegate<T>> createState();

  void debugFillProperties(DiagnosticPropertiesBuilder properties) 


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

复制代码
  • 这里需要重新回顾下InheritedProvider类
    • 这地方做了一个很重要的操作,将_CreateInheritedProvider实例赋值给 _delegate
    • buildWithChild方法中_InheritedProviderScope的owner接受了InheritedProvider本身的实例
    • 结合这俩个就有戏了,再来看下_InheritedProviderScope类
class InheritedProvider<T> extends SingleChildStatelessWidget 
  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);

  final _Delegate<T> _delegate;
  final bool? _lazy;

  ...

  @override
  Widget buildWithChild(BuildContext context, Widget? child) 
    ,,,
    return _InheritedProviderScope<T>(
      owner: this,
      debugType: kDebugMode ? '$runtimeType' : '',
      child: builder != null
          ? Builder(
              builder: (context) => builder!(context, child),
            )
          : child!,
    );
  

复制代码
  • _InheritedProviderScope
    • createElement方法传入_InheritedProviderScope本身的实例
    • 关键的在_InheritedProviderScopeElement类中
class _InheritedProviderScope<T> extends InheritedWidget 
  const _InheritedProviderScope(
    required this.owner,
    required this.debugType,
    required Widget child,
  ) : super(child: child);

  final InheritedProvider<T> owner;
  final String debugType;

  @override
  bool updateShouldNotify(InheritedWidget oldWidget) 
    return false;
  

  @override
  _InheritedProviderScopeElement<T> createElement() 
    return _InheritedProviderScopeElement<T>(this);
  

复制代码
  • _InheritedProviderScopeElement类,我就直接精简到关键代码了
    • 有没有感觉InheritedWidget很像StatefulWidget,实际他俩最终都是继承Widget,未对Widget的建造者模式那层封装,所以有俩层结构;而StatelessWidget将建造者模式那层进行了封装,所以只有一层结构
    • 下面的关键代码看到没! widget.owner._delegate.createState() ... 这地方调用了_CreateInheritedProvider类的createState() 方法,安心了
    • performRebuild:该回调会在setState或者build的时候会触发;此处做了一个判断,只会在第一次build的时候触发
    • 这里可以确定_CreateInheritedProvider类中的createState方法一定会被调用;接下来看看其方法里面调用的 _CreateInheritedProviderState类
class _InheritedProviderScopeElement<T> extends InheritedElement
    implements InheritedContext<T> 
  _InheritedProviderScopeElement(_InheritedProviderScope<T> widget)
      : super(widget);

  ...

  @override
  void performRebuild() 
    if (_firstBuild) 
      _firstBuild = false;
      _delegateState = widget.owner._delegate.createState()..element = this;
    
    super.performRebuild();
  

  ...

复制代码
  • 流程图示

_InheritedProviderScopeElement

  • _CreateInheritedProviderState:这个类做了很多事情,很多的主体逻辑的都在此处理
    • 该类代码很多,此处只留下我们需要关注的代码,因为省略了很多代码,从下面的主体代码来看,流程就清楚了:create、startListening、dispose 都有
    • 但是这些变量是依附在delegate上的,这个delegate是个啥?需要看下继承的抽象类  _DelegateState
class _CreateInheritedProviderState<T> extends _DelegateState<T, _CreateInheritedProvider<T>> 
  VoidCallback? _removeListener;
  bool _didInitValue = false;
  T? _value;
  _CreateInheritedProvider<T>? _previousWidget;

  @override
  T get value 
    ...

    if (!_didInitValue) 
      _didInitValue = true;
      if (delegate.create != null) 
        assert(debugSetInheritedLock(true));
        try 
          ...
          _value = delegate.create!(element!);
         finally 
          ...
        
        ...
      
      ...
    

    element!._isNotifyDependentsEnabled = false;
    _removeListener ??= delegate.startListening?.call(element!, _value as T);
    element!._isNotifyDependentsEnabled = true;
    assert(delegate.startListening == null || _removeListener != null);
    return _value as T;
  

  @override
  void dispose() 
    super.dispose();
    _removeListener?.call();
    if (_didInitValue) 
      delegate.dispose?.call(element!, _value as T);
    
  

  ...

复制代码
  • _DelegateState
    • delegate是通过 _InheritedProviderScopeElement的实例获取到了owner然后获取到了 _delegate变量
    • _delegate这个变量是在InheritedProvider类中的实例化 _CreateInheritedProvider赋值给他的,不信的话,可以返回去看看
    • 好吉尔绕!!!
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
    • 现在还有个问题,element这个变量在哪实例化的?怎么大家这么随便用它!就不怕它为空吗?
    • 直接带大家来_InheritedProviderScopeElement里面看了,上面已经回顾了到这个必定实例化这个上下文类的流程
    • performRebuild回调中,在调用createState()方法的时候,给element赋值了,element = this
    • 所以在_CreateInheritedProviderState类中,可以随便使用element 这个变量,他的值肯定不为空!
class _InheritedProviderScopeElement<T> extends InheritedElement
    implements InheritedContext<T> 
  _InheritedProviderScopeElement(_InheritedProviderScope<T> widget)
      : super(widget);

  ...

  @override
  void performRebuild() 
    if (_firstBuild) 
      _firstBuild = false;
      _delegateState = widget.owner._delegate.createState()..element = this;
    
    super.performRebuild();
  

  ...

复制代码

不知道大家对这流程有没有个清晰的印象

  • 来看看这山路十八弯的初始化链路图

_CreateInheritedProviderState

有了上面分析出的element和_delegate不为空的,且 _delegate能直接访问 _CreateInheritedProvider这个实例基础,再来看下 _CreateInheritedProviderState代码

  1. get 流程
    1. 我们传入的create会直接赋值给 _value,现在这个 _value,就是我们在外面传进来的那个XxxProvider实例了!
    2. 底下也调用了 startListening,说明从外面传进来的这个回调也调用了,将 上下文实例 和 传进来的XxxProvider实例 作为入参传进了这个回调中,此处传进来的回调也通过 .call 被调用了!
  2. dispose 流程
    1. 调用startListening方法时,该方法会返回一个移除监听Function
    2. 移除监听的Function在dispose时被调用,移除给XxxProvider添加的监听
    3. 从外部传入的dispose方法,也在此处被执行
    4. OK!回收资源的操作在此处都搞定了!
class _CreateInheritedProviderState<T> extends _DelegateState<T, _CreateInheritedProvider<T>> 
  VoidCallback? _removeListener;
  bool _didInitValue = false;
  T? _value;
  _CreateInheritedProvider<T>? _previousWidget;

  @override
  T get value 
    ...

    if (!_didInitValue) 
      _didInitValue = true;
      if (delegate.create != null) 
        assert(debugSetInheritedLock(true));
        try 
          ...
          _value = delegate.create!(element!);
         finally 
          ...
        
        ...
      
      ...
    

    element!._isNotifyDependentsEnabled = false;
    _removeListener ??= delegate.startListening?.call(element!, _value as T);
    element!._isNotifyDependentsEnabled = true;
    assert(delegate.startListening == null || _removeListener != null);
    return _value as T;
  

  @override
  void dispose() 
    super.dispose();
    _removeListener?.call();
    if (_didInitValue) 
      delegate.dispose?.call(element!, _value as T);
    
  

  ...

复制代码
  • 关键的就是startListening回调了,来看下他的逻辑
    • _startListening在此处 addListener 了!ChangeNotifier 是 Listenable 实现类,姑且把它当成访问者模式也可,所以这个value就是我们从外面传进来的 XxxProvider
    • 返回了一个VoidCallback的Function,里面是移除监听逻辑
class ListenableProvider<T extends Listenable?> extends InheritedProvider<T> 
  ListenableProvider(
    Key? key,
    required Create<T> create,
    Dispose<T>? dispose,
    bool? lazy,
    TransitionBuilder? builder,
    Widget? child,
  ) : super(
          key: key,
          startListening: _startListening,
          create: create,
          dispose: dispose,
          lazy: lazy,
          builder: builder,
          child: child,
        );

  ...

  static VoidCallback _startListening(InheritedContext e, Listenable? value,) 
    value?.addListener(e.markNeedsNotifyDependents);
    return () => value?.removeListener(e.markNeedsNotifyDependents);
  

复制代码

还有最后一个问题!!!

需要调用_startListening方法,必须调用 _CreateInheritedProviderState类里面的 get value

在哪个初始化入口,使用这个  get value 呢?

  • 这里直接给出结论了,还是在 _InheritedProviderScopeElement这个上下文类里面
    • reassemble:全局状态的初始化逻辑或热重载的时候被调用
    • _delegateState首先在performRebuild回调中会赋初值
    • 在reassemble回调中,_delegateState调用了value( _delegateState.value )
    • 所以 get value 肯定会在初始化的时候被调用,上面流程是通顺的
class _InheritedProviderScopeElement<T> extends InheritedElement
    implements InheritedContext<T> 
  _InheritedProviderScopeElement(_InheritedProviderScope<T> widget)
      : super(widget);

  late _DelegateState<T, _Delegate<T>> _delegateState;

  ...

  @override
  void performRebuild() 
    if (_firstBuild) 
      _firstBuild = false;
      _delegateState = widget.owner._delegate.createState()..element = this;
    
    super.performRebuild();
  

  @override
  void reassemble() 
    super.reassemble();

    final value = _delegateState.hasValue ? _delegateState.value : null;
    if (value is ReassembleHandler) 
      value.reassemble();
    
  

  ...

复制代码

总结

上面分析完了添加监听,以及相关的初始化链路和调用链路

  • 可以把流程图整全了,来看看

刷新逻辑

刷新逻辑也是相当之绕啊;各种debug,在framework里面各种打断点,终于把流程理通了!突然感觉自己打通了任督二脉!

作者为了实现这个刷新逻辑,和系统api做了大量的交互,相当的精彩!

我会尽力将这个精彩纷呈的操作,展现给大家!

触发

  • ListenableProvider
    • 这地方逻辑很简单,添加了InheritedContext这个上下文类中的markNeedsNotifyDependents方法
    • 说明,我们在外部使用notifyListeners() 的时候,一定会触发InheritedContext实现类中的markNeedsNotifyDependents方法
class ListenableProvider<T extends Listenable?> extends InheritedProvider<T> 
  ListenableProvider(
    Key? key,
    required Create<T> create,
    Dispose<T>? dispose,
    bool? lazy,
    TransitionBuilder? builder,
    Widget? child,
  ) : super(
          key: key,
          startListening: _startListening,
          create: create,
          dispose: dispose,
          lazy: lazy,
          builder: builder,
          child: child,
        );

  ...

  static VoidCallback _startListening(InheritedContext e, Listenable? value,) 
    value?.addListener(e.markNeedsNotifyDependents);
    return () => value?.removeListener(e.markNeedsNotifyDependents);
  

复制代码
  • _InheritedProviderScopeElement: _InheritedProviderScopeElement是InheritedContext的实现类
    • 还是要来这个类看看,只保留了和markNeedsNotifyDependents有关的代码
    • markNeedsNotifyDependents回调作用,总的来说:会将强制依赖于T窗口小部件进行重建
    • 说的这么笼统没啥用,下面会全面分析,他是怎么做到让依赖于T窗口小部件进行重建的! 我想了下,还是观察者模式的应用。。。
class _InheritedProviderScopeElement<T> extends InheritedElement implements InheritedContext<T> 
  _InheritedProviderScopeElement(_InheritedProviderScope<T> widget)
      : super(widget);

  ...

  @override
  void markNeedsNotifyDependents() 
    if (!_isNotifyDependentsEnabled) 
      return;
    

    markNeedsBuild();
    _shouldNotifyDependents = true;
  

  ...

复制代码

刷新流程

咱们现在来理一下刷新的流程!

  • markNeedsNotifyDependents
    • 当我们使用 notifyListeners(),就会触发,这个回调
    • 此处调用了 markNeedsBuild(),然后给 _shouldNotifyDependents 设置为true
    • 必备操作,来看下 markNeedsBuild() 作用
class _InheritedProviderScopeElement<T> extends InheritedElement implements InheritedContext<T> 
  _InheritedProviderScopeElement(_InheritedProviderScope<T> widget)
      : super(widget);

  bool _shouldNotifyDependents = false;
  ...

  @override
  void markNeedsNotifyDependents() 
    if (!_isNotifyDependentsEnabled) 
      return;
    

    markNeedsBuild();
    _shouldNotifyDependents = true;
  

  ...

复制代码
  • markNeedsBuild
    • _InheritedProviderScopeElement最终继承的还是Element抽象类,markNeedsBuild()方法是Element中的
    • Element类是一个实现了BuildContext抽象类中抽象方法的抽象类,该类十分重要
    • 这个方法花里胡哨的代码写了一大堆,他最主要的功能:就是会调用Element的performRebuild()方法,然后触发ComponentElement的build()方法,最终触发_InheritedProviderScopeElement的build方法
    • _InheritedProviderScopeElement extends InheritedElement extends ProxyElement extendsComponentElement extends Element
abstract class Element extends DiagnosticableTree implements BuildContext 
  ...

  void markNeedsBuild() 
    assert(_lifecycleState != _ElementLifecycle.defunct);
    if (_lifecycleState != _ElementLifecycle.active)
      return;
    assert(owner != null);
    assert(_lifecycleState == _ElementLifecycle.active);
    assert(() 
      if (owner!._debugBuilding) 
        assert(owner!._debugCurrentBuildTarget != null);
        assert(owner!._debugStateLocked);
        if (_debugIsInScope(owner!._debugCurrentBuildTarget!))
          return true;
        if (!_debugAllowIgnoredCallsToMarkNeedsBuild) 
          final List<DiagnosticsNode> information = <DiagnosticsNode>[
            ErrorSummary('setState() or markNeedsBuild() called during build.'),
            ErrorDescription(
              'This $widget.runtimeType widget cannot be marked as needing to build because the framework '
              'is already in the process of building widgets.  A widget can be marked as '
              'needing to be built during the build phase only if one of its ancestors '
              'is currently building. This exception is allowed because the framework '
              'builds parent widgets before children, which means a dirty descendant '
              'will always be built. Otherwise, the framework might not visit this '
              'widget during this build phase.',
            ),
            describeElement(
              'The widget on which setState() or markNeedsBuild() was called was',
            ),
          ];
          if (owner!._debugCurrentBuildTarget != null)
            information.add(owner!._debugCurrentBuildTarget!.describeWidget('The widget which was currently being built when the offending call was made was'));
          throw FlutterError.fromParts(information);
        
        assert(dirty); // can only get here if we're not in scope, but ignored calls are allowed, and our call would somehow be ignored (since we're already dirty)
       else if (owner!._debugStateLocked) 
        assert(!_debugAllowIgnoredCallsToMarkNeedsBuild);
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary('setState() or markNeedsBuild() called when widget tree was locked.'),
          ErrorDescription(
            'This $widget.runtimeType widget cannot be marked as needing to build '
            'because the framework is locked.',
          ),
          describeElement('The widget on which setState() or markNeedsBuild() was called was'),
        ]);
      
      return true;
    ());
    if (dirty)
      return;
    _dirty = true;
    owner!.scheduleBuildFor(this);
  

  ...
  • build
    • 这里说明下,这个子类调用父类方法,然后父类调用自身方法,是先触发这个子类的重写方法,然后可以通过 super. 的方式去执行父类逻辑
    • 上面给_shouldNotifyDependents设置为true,所以build内部逻辑会执行notifyClients(widget)方法
    • 接下来看下notifyClients(widget)方法
class _InheritedProviderScopeElement<T> extends InheritedElement implements InheritedContext<T> 
  _InheritedProviderScopeElement(_InheritedProviderScope<T> widget)
      : super(widget);

  bool _shouldNotifyDependents = false;
  ...

    @override
  Widget build() 
    if (widget.owner._lazy == false) 
      value; // this will force the value to be computed.
    
    _delegateState.build(
      isBuildFromExternalSources: _isBuildFromExternalSources,
    );
    _isBuildFromExternalSources = false;
    if (_shouldNotifyDependents) 
      _shouldNotifyDependents = false;
      notifyClients(widget);
    
    return super.build();
  

  ...

复制代码
  • notifyClients:notifyClients()是InheritedElement类中的,notifyClients()方法是ProxyElement类中的一个抽象方法,InheritedElement在此处做了一个实现
    1. notifyClients()是一个非常非常重要的方法,它内部有个for循环,遍历了_dependents这个HashMap类型的所有key值, _dependents的key是Element类型
      1. 什么是Element?它可以表示为Widget在树中特定位置的实例,一个Element可以形成一棵树(想想每个Container都有Element,然后其child再套其它的widget,这样就形成了一颗树)
      2. Element在此处将其理解为:本身Widget和其子节点形成的树,Element是这棵树的头结点,这特定位置的节点是实例化的,对这个特定位置的实例节点操作,会影响到他的子节点
      3. Widget的createElement()方法会实例化Element
    2. 这地方遍历_dependents的key取Element,可以猜测:他肯定是想取某个元素或者说某个Widget
    3. 取到相关Element实例后,她会传入notifyDependent(oldWidget, dependent)方法中
    4. 接下来,需要看看notifyDependent(oldWidget, dependent)方法逻辑了
class InheritedElement extends ProxyElement 
  final Map<Element, Object?> _dependents = HashMap<Element, Object?>();

  ...

  @override
  void notifyClients(InheritedWidget oldWidget) 
    assert(_debugCheckOwnerBuildTargetExists('notifyClients'));
    for (final Element dependent in _dependents.keys) 
      assert(() 
        // check that it really is our descendant
        Element? ancestor = dependent._parent;
        while (ancestor != this && ancestor != null)
          ancestor = ancestor._parent;
        return ancestor == this;
      ());
      // check that it really depends on us
      assert(dependent._dependencies!.contains(this));
      notifyDependent(oldWidget, dependent);
    
  
  • notifyDependent
    • if (dependencies is _Dependency) 这判断的逻辑题里面还有很多逻辑,是作者在BuildContext上面搞了一个select扩展方法(判断是否需要刷新),但和现在讲了刷新流程无关,我在里面绕了好久,凎!
    • 去掉上面的逻辑就简单了,shouldNotify赋值为true,最后调用dependent.didChangeDependencies()
    • dependent还记得是啥吗?是父类里面循环取得的Element实例
    • 这地方直接去掉super操作,这也是系统建议的,我们可以重写notifyDependent方法,自定义相关逻辑;因为有时我们需要可选择性的调用dependent.didChangeDependencies()!
class _InheritedProviderScopeElement<T> extends InheritedElement implements InheritedContext<T> 
  _InheritedProviderScopeElement(_InheritedProviderScope<T> widget)
      : super(widget);

  ...

  @override
  void notifyDependent(InheritedWidget oldWidget, Element dependent) 
    final dependencies = getDependencies(dependent);

    if (kDebugMode) 
      ProviderBinding.debugInstance.providerDidChange(_debugId);
    

    var shouldNotify = false;
    if (dependencies != null) 
      if (dependencies is _Dependency<T>) 
        ...
       else 
        shouldNotify = true;
      
    

    if (shouldNotify) 
      dependent.didChangeDependencies();
    
  

  ...

复制代码
  • didChangeDependencies
    • didChangeDependencies逻辑就很简单了,会调用markNeedsBuild()
    • 可以理解为:最终会调用该Widget的build方法
    • markNeedsBuild()就不讲了,内部涉及逻辑太多了,还涉及bind类,还会涉及到绘制流程,我嘞个去。。。
abstract class Element extends DiagnosticableTree implements BuildContext 
  ...

  @mustCallSuper
  void didChangeDependencies() 
    assert(_lifecycleState == _ElementLifecycle.active); // otherwise markNeedsBuild is a no-op
    assert(_debugCheckOwnerBuildTargetExists('didChangeDependencies'));
    markNeedsBuild();
  

  ...

复制代码

现在有个超纠结的事情,这个点关乎整个刷新流程的枢纽!

InheritedElement中的_dependents这个map的key是Element,这个Element是什么?上面所有流程都是为了调用 _dependents这个Map中key(Element)的markNeedsBuild()方法,最终是为了调用这个Element的Widget的build方法!

大家明白了吗?我们就算大胆去蒙,去猜,去赌,这个Widget十有八九就是Consumer这类刷新Widget啊!

但是!但是!他到底是怎么将这类刷新Widget添加到InheritedElement的 _dependents变量中的呢 !?

  • 上述流程图示

BuildContext

插播一个小知识点,这个知识和下述内容相关,这边先介绍一下

BuildContext是什么?

  • BuildContext
    • 每个抽象方法上面注释超级多,我删掉了(占篇幅),有兴趣的可以自己去源码里看看
    • BuildContext就是抽象类,是约定好的一个抽象类,相关方法的功能已经被约定,你如果想实现这个抽象类类,相关方法功能实现可以有出入,但不应该偏离抽象方法注释所描述的功能范围
abstract class BuildContext 
  Widget get widget;

  BuildOwner? get owner;

  bool get debugDoingBuild;

  RenderObject? findRenderObject();

  Size? get size;

  InheritedWidget dependOnInheritedElement(InheritedElement ancestor,  Object aspect );

  T? dependOnInheritedWidgetOfExactType<T extends InheritedWidget>( Object? aspect );

  InheritedElement? getElementForInheritedWidgetOfExactType<T extends InheritedWidget>();

  T? findAncestorWidgetOfExactType<T extends Widget>();

  T? findAncestorStateOfType<T extends State>();

  T? findRootAncestorStateOfType<T extends State>();

  T? findAncestorRenderObjectOfType<T extends RenderObject>();

  void visitAncestorElements(bool Function(Element element) visitor);

  void visitChildElements(ElementVisitor visitor);

  DiagnosticsNode describeElement(String name, DiagnosticsTreeStyle style = DiagnosticsTreeStyle.errorProperty);

  DiagnosticsNode describeWidget(String name, DiagnosticsTreeStyle style = DiagnosticsTreeStyle.errorProperty);

  List<DiagnosticsNode> describeMissingAncestor( required Type expectedAncestorType );

  DiagnosticsNode describeOwnershipChain(String name);

复制代码
  • StatelessWidget:看下StatelessWidget对BuildContext的实现(StatefulWidget同理,不贴了)
    • 代码超级简单,StatelessWidget抽象了build方法,入参为BuildContext
    • createElement()方法实例了StatelessElement类,并将StatelessWidget本身实例传入
    • StatelessElement里面实现了ComponentElement的build方法:该方法调用了widget里面的build方法,并将本身的实例传入,流程通了,此处调用StatelessWidget的build方法,并传入了BuildContext的实现类
    • ComponentElement的父类中肯定有实现BuildContext,往上看看
abstract class StatelessWidget extends Widget 
  const StatelessWidget( Key? key ) : super(key: key);

  @override
  StatelessElement createElement() => StatelessElement(this);

  @protected
  Widget build(BuildContext context);


class StatelessElement extends ComponentElement 
  StatelessElement(StatelessWidget widget) : super(widget);

  @override
  StatelessWidget get widget => super.widget as StatelessWidget;

  @override
  Widget build() => widget.build(this);

  @override
  void update(StatelessWidget newWidget) 
    super.update(newWidget);
    assert(widget == newWidget);
    _dirty = true;
    rebuild();
  

复

以上是关于Flutter Provider源码分析的主要内容,如果未能解决你的问题,请参考以下文章

Flutter Bloc源码分析

自定义状态管理Provider以及原理分析

自定义状态管理Provider以及原理分析

Flutter状态管理-Provider的使用和源码解析

社区说|Flutter 主流状态管理框架 provider get 分析

源码篇Flutter Bloc背后的思想,一篇纠结的文章