4. Flutter Provider

130 阅读3分钟

和InheritedWidget 类似的,我们来分析 Provider , 还是设计到 收集通知两个过程

1. 收集过程


void main() {
  runApp(
      // 可以使用多个 Provider
      MultiProvider(
    providers: [
    // ChangeNotifierProvider 其实就是 ChangeNotifier 容器,使用组合方式来接入 ChangeNotifier
      ChangeNotifierProvider(create: (_) {
        return HYCounterViewModel();
      }),
    ],
    child: const MyApp(),
  ));
}

class HYCounterViewModel extends ChangeNotifier {
  int _counter = 0;
  HYCounterViewModel();
  int get counter => _counter;
  set counter(int value) {
    _counter = value;
    notifyListeners();
  }

  @override
  void addListener(VoidCallback listener) {
    // TODO: implement addListener
    super.addListener(listener);
  }
}


class ProviceShareState extends StatefulWidget {
  const ProviceShareState({super.key});

  @override
  State<ProviceShareState> createState() => _ProviceShareStateState();
}

class _ProviceShareStateState extends State<ProviceShareState> {
  int _count = 0;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Provider test"),
      ),
      body: Column(
        children: [
          HYShowData01(),
          HYShowData02(),
          Consumer<HYCounterViewModel>(builder: (context, counterVM, widget) {
            return FloatingActionButton(
                child: Icon(Icons.pets),
                onPressed: () {
                  counterVM.counter += 1;
                });
          })
        ],
      ),
    );
  }
}

class HYShowData01 extends StatelessWidget {
  const HYShowData01({super.key});

  @override
  Widget build(BuildContext context) {
    print("HYShowData01 --- build");
    return Card(
      color: Colors.red,
      child: Text("当前计数1: ${Provider.of<HYCounterViewModel>(context).counter}"),
    );
  }
}

class HYShowData02 extends StatefulWidget {
  const HYShowData02({super.key});

  @override
  State<HYShowData02> createState() => _HYShowData02State();
}

class _HYShowData02State extends State<HYShowData02> {
  @override
  Widget build(BuildContext context) {
    print("HYShowData02 --- build");
    return Card(
      color: Colors.blue,
      child: MYConsumer<HYCounterViewModel>(
        builder: (context, value, child) {
          return Text("当前计数2: ${value.counter}");
        },
      ),
    );
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    print("didChangeDependencies: _HYShowData02State");
  }

  @override
  void didUpdateWidget(covariant HYShowData02 oldWidget) {
    super.didUpdateWidget(oldWidget);
    print("didUpdateWidget: _HYShowData02State");
  }
}

class MYConsumer<T> extends Consumer<T> {
  //  MYConsumer({Key? key, required Widget Function(BuildContext, dynamic, Widget?) builder})
  MYConsumer({super.key, required super.builder});
  @override
  Widget build(BuildContext context) {
    return super.build(context);
  }
}

上面有两个地方设计到收集

// 收集1
Text("当前计数1: ${Provider.of<HYCounterViewModel>(context).counter}")

//收集2
MYConsumer<HYCounterViewModel>(
    builder: (context, value, child) {
      return Text("当前计数2: ${value.counter}");
    },
 )

下面我主要看看这里到底收集那些

1.1 我们先看第一种 Provider.of<HYCounterViewModel>(context).counter ,这里的context 是 HYShowData01Element


static T of<T>(BuildContext context, {bool listen = true}) {
    
    //T: HYCounterViewModel,    _InheritedProviderScope<HYCounterViewModel?>
    //  InheritedElement? ancestor =  _inheritedWidgets![ _InheritedProviderScope<HYCounterViewModel?> ]; , 没有添加depend
    final inheritedElement = _inheritedElementOf<T>(context);

    if (listen) {
      // 这里添加绑定, 这个和 InheritedWidget是一样的,主要是让 ancestor 用set 存储这些 context
      // 方便后面的noti
      context.dependOnInheritedWidgetOfExactType<_InheritedProviderScope<T?>>();
    }

    // value:  HYCounterViewModel的对象
    final value = inheritedElement?.value;
 
    // 返回 HYCounterViewModel的对象
    return value as T;
 }

// 这个方法其实就是为了 组成  _InheritedProviderScope<HYCounterViewModel?> 一个类型 
// 然后去 子Element._inheritedWidgets 去找当前的  _InheritedProviderScope<HYCounterViewModel?> Element
static _InheritedProviderScopeElement<T?>? _inheritedElementOf<T>(BuildContext context) {
  
    final inheritedElement = context.getElementForInheritedWidgetOfExactType<
        _InheritedProviderScope<T?>>() as _InheritedProviderScopeElement<T?>?;

    return inheritedElement;
  }
  
  // Element
  @override
  InheritedElement? getElementForInheritedWidgetOfExactType<T extends InheritedWidget>() {
    final InheritedElement? ancestor = _inheritedWidgets == null ? null : _inheritedWidgets![T];
    return ancestor;
  }


1.2 我们看第二种, 其实和第一种方式是一样的 Provider.of<T>(context),


MYConsumer<HYCounterViewModel>(
    builder: (context, value, child) {
      return Text("当前计数2: ${value.counter}");
    },
 )

//Consumer 里面会有个build
Widget buildWithChild(BuildContext context, Widget? child) {
    return builder(
      context,
      // 很明显这里和第一种方式是一样的,只是做了一层封装而已
      Provider.of<T>(context),
      child,
    );
  }

2. 通知过程

//HYCounterViewModel => 主动调用notifyListeners();
// ChnageNotifier
 void notifyListeners() {
    for (int i = 0; i < end; i++) {
         //  这个listeners[0] : 存储了一个函数地址 _InheritedProviderScopeElement 里面的 void markNeedsNotifyDependents()
         // 这里就完成了通知过程
         _listeners[i]?.call();
    }
 }

接下来我们看看 _listeners 是怎么设置的

// ChangeNotifier 类中  ,因为这里调用次数太多,我们在 HYCounterViewModel中 重写 这个方法
@override
  void addListener(VoidCallback listener) {
    assert(ChangeNotifier.debugAssertNotDisposed(this));
    if (kFlutterMemoryAllocationsEnabled && !_creationDispatched) {
      MemoryAllocations.instance.dispatchObjectCreated(
        library: _flutterFoundationLibrary,
        className: '$ChangeNotifier',
        object: this,
      );
      _creationDispatched = true;
    }
    if (_count == _listeners.length) {
      if (_count == 0) {
        _listeners = List<VoidCallback?>.filled(1, null);
      } else {
        final List<VoidCallback?> newListeners =
            List<VoidCallback?>.filled(_listeners.length * 2, null);
        for (int i = 0; i < _count; i++) {
          newListeners[i] = _listeners[i];
        }
        _listeners = newListeners;
      }
    }
    _listeners[_count++] = listener;
  }
  
  
  // HYCounterViewModel, 在这里打个断点
  @override
  void addListener(VoidCallback listener) {
    // TODO: implement addListener
    super.addListener(listener);
    
 }
  

我们再次进入收集过程

image.png

Provider.of<HYCounterViewModel>(context) =>

再次回到前面方法

static T of<T>(BuildContext context, {bool listen = true}) {

    final inheritedElement = _inheritedElementOf<T>(context);

    if (listen) {
      context.dependOnInheritedWidgetOfExactType<_InheritedProviderScope<T?>>();
    }

    // 这里会触发 下面的_InheritedProviderScopeElement  get方法 
    final value = inheritedElement?.value;
 
    return value as T;
 }
 
 // _InheritedProviderScopeElement
 // [1 delegate]. 这个 _delegateState: _CreateInheritedProviderState
 @override
  T get value => _delegateState.value;
  
// 进入 _CreateInheritedProviderState 
 @override
  T get value {
      //[2 delegate]. 是一个 get方法  _DelegateState 类里面:   
      // D get delegate => element!.widget.owner._delegate as D 
      // 2.1 element: _InheritedProviderScopeElement (_InheritedProviderScope<HYCounterViewModel?>)
      // 2.2 widget: _InheritedProviderScope (_InheritedProviderScope<HYCounterViewModel?>)
      // 2.3 owner: ChangeNotifierProvider (ChangeNotifierProvider<HYCounterViewModel>)
      // 2.4 _delegate : _CreateInheritedProvider (Instance of '_CreateInheritedProvider<HYCounterViewModel>')
 
     _removeListener ??= delegate.startListening?.call(element!, _value as T);
     // HYCounterViewModel对象
     return _value as T;
  }
  
  // delegate.startListening?.call(element!, _value as T)  => 
  // ListenableProvider 
  static VoidCallback _startListening(
    InheritedContext<Listenable?> e,
    Listenable? value,
  ) {
  // value: HYCounterViewModel对象
  // 这里传递的是  e.markNeedsNotifyDependents 是_InheritedProviderScopeElement 里面的函数 markNeedsNotifyDependents ,这个函数就是标记重新更新用的
    value?.addListener(e.markNeedsNotifyDependents);
    return () => value?.removeListener(e.markNeedsNotifyDependents);
  }

 

3.再看 RunApp 里面传入的 MultiProvider

runApp(
      // 可以使用多个 Provider
      MultiProvider(
    providers: [
      ChangeNotifierProvider(create: (_) {
        return HYCounterViewModel();
      }),
    ],
    child: const MyApp(),
  ));

我们先看看 ChangeNotifierProvider

ChangeNotifierProvider(create: (_) {
   return HYCounterViewModel();
})

通过继承关系我们可以看到下面的

ChangeNotifierProvider extends ListenableProvider extends InheritedProvider extends SingleChildStatelessWidget extends StatelessWidget implements SingleChildWidget

ChangeNotifierProvider 中有个 create参数,我们跟进去


/*
 1. InheritedProvider._delegate  = _CreateInheritedProvider(create)
 2. 我们找到了 _CreateInheritedProvider 
*/
InheritedProvider({
    Key? key,
    // 这里找到了create参数
    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,
        // 拿到了create 去给  _CreateInheritedProvider
        _delegate = _CreateInheritedProvider(
          create: create,
          update: update,
          updateShouldNotify: updateShouldNotify,
          debugCheckInvalidValueType: debugCheckInvalidValueType,
          startListening: startListening,
          dispose: dispose,
        ),
        super(key: key, child: child);
        
       

进入 _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
  // 通过_CreateInheritedProvider 创建  _CreateInheritedProviderState 
  // _CreateInheritedProviderState 这个state 就是前面分析调用get方法来收集用的
  _CreateInheritedProviderState<T> createState() =>
      _CreateInheritedProviderState();
}