Flutter Provider实现原理

Provider源码分析

ChangeNotifierProvider、ChangeNotifier、Consumer的关系


关系

一、ChangeNotifierProvider

1、ChangeNotifierProvider的父类ListenableProvider,ListenableProvider中实现了_startListening方法,_startListening主要是将Element的刷新方法添加到ChangeNotifier中的_listeners中

class ListenableProvider extends 
  ListenableProvider({
  ...
  }) : super(
          key: key,
          startListening: _startListening,
         ...
        );
  static VoidCallback _startListening(
    InheritedContext e,
    Listenable? value, //该对象其实就是ChangeNotifier对象
  ) {
    ///添加element刷新方法
    value?.addListener(e.markNeedsNotifyDependents);
    return () => value?.removeListener(e.markNeedsNotifyDependents);
  }

2、ListenableProvider将startListening传入其父类InheritedProvider,InheritedProvider主要是创建delegate = _CreateInheritedProvider。这个delegate就是_CreateInheritedProvider中delegate.startListening中的delegate

二、ChangNotifier

1、ChangNotifier负责更新UI


image.png

ChangeNotifier中notifyListeners,通过遍历_listeners,实现强制刷新UI

void notifyListeners() {
    assert(_debugAssertNotDisposed());
    if (_count == 0)
      return;
    _notificationCallStackDepth++;

    final int end = _count;
    for (int i = 0; i < end; i++) {
      try {
        _listeners[i]?.call();
      } catch (exception, stack) {
       ...
    }

三、Consumer

1、Consumer:包裹待刷新UI,在buildWithChild中将Provider.of(context)传入builder方法


原理
class Consumer extends SingleChildStatelessWidget
...
 @override
  Widget buildWithChild(BuildContext context, Widget? child) {
    return builder(
      context,
      Provider.of(context),//传入ChangeNotifier
      child,
    );
  }

2、解析 Provider.of(context)
Provider.of(context)是获取ChangeNotifier对象的方法
Provider.of中通过传入的context,获取父视图为inheritedElement的对象
获取到inheritedElement,通过inheritedElement.getValue的方式获取ChangeNotifier对象

static T of(BuildContext context, {bool listen = true}) {
   
  ///获取父视图为inheritedElement的对象
    final inheritedElement = _inheritedElementOf(context); 

    if (listen) {
     context.dependOnInheritedWidgetOfExactType<_InheritedProviderScope>();
    }
  ///调用inheritedElement.getValue获取Provider对象的对象
    final value = inheritedElement?.value;
    ...
    return value as T;
  }

7、继续查看inheritedElement?.value。通过断点可以进入_CreateInheritedProvider 类中get Value方法。调用startListening将当前Consumer包裹的element添加到Prorivder的_listeners数组中

class _CreateInheritedProvider extends _Delegate {
  ...
  @override
  T get value {
     ...
    element!._isNotifyDependentsEnabled = false;
    ///调用startListening将当前Consumer包裹的element添加到ChangeNotifier的_listeners数组中
    _removeListener ??= delegate.startListening?.call(element!, _value as T);
    element!._isNotifyDependentsEnabled = true;
    assert(delegate.startListening == null || _removeListener != null);
    return _value as T;
  }

四、总结

通过调用notifyListeners()来刷新所有Consumer完整的Provider执行流程大概就是这样,流程图如下


完整流程图

你可能感兴趣的:(Flutter Provider实现原理)