若是对Provider的使用已经很熟练,能够跳过这部份内容,直接看过程分析部分 Flutter状态管理Provider(二)过程分析html
Demo代码仓库 入口:main_provider.dartgit
[Provider](https://github.com/rrousselGit/provider)
简单翻译来讲,Provider:依赖注入与状态管理的结合,而且对外提供Widget使用。使用widget代替纯Dart对象,好比说Stream。由于widget简单,强大且可扩展。使用Provider,能够保证:可维护性(强制的单向数据流),可测试性,健壮性等等。
A mixture between dependency injection (DI) and state management, built with widgets for widgets.It purposefully uses widgets for DI/state management instead of dart-only classes like Stream.
The reason is, widgets are very simple yet robust and scalable.
By using widgets for state management, provider can guarantee:
复制代码
若是说页面是静态,拿到数据,渲染完就完事了.压根就不须要状态管理。 不幸的是,页面不可能全是静态。页面须要响应数据变化(网络数据?用户操做产生的数据?),更新UI。同时,数据变化的影响,不单单是组件内,还有多是页面内其余组件,甚至于应用内其余页面github
数据即为状态。从数据变化到通知界面更新的过程,咱们称之为状态管理 状态管理要尽量的把这个过程独立出来,让动态界面如同静态页面通常简单。redux
- setState
- FutureBuilder/StreamBuilder/BLoc
- Provider/ScopedModel
- redux/Fish-redux
复制代码
有了状态管理的介绍,咱们能够参考Provider,经过手上现有的组件,实现一个简易版的Provider。要用到的系统组件:bash
状态管理最基础的一个实现markdown
class _SetStateDemoWidgetState extends State<SetStateDemoWidget> { int count = 0; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(setStateDemoTitle),), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text("计数:$count"), RaisedButton( child: Text("increment"), onPressed: () => setState(() => count++), ) ], ), ), ); } } 复制代码
用CountProvider继承InheritedWidget来保存数据。 经过context.getElementForInheritedWidgetOfExactType拿到CountProvider中的数据。 这个context必定要注意,只能用CountProvider子widget的BuildContext。CountProvider的查找是经过context往上的。 注意这个地方,咱们只是单纯的拿数据,尚未用到InheritedWidget能够控制子widget从新构建的功能。网络
///首先咱们要有个地方存放咱们的数据 class CountProvider extends InheritedWidget { final int count; CountProvider({Key key, this.count, Widget child}) : super(key: key, child: child); @override bool updateShouldNotify(CountProvider old) { return true; } } class ProviderDemoWidget1 extends StatefulWidget { ProviderDemoWidget1({Key key}) : super(key: key); @override _ProviderDemoWidget1State createState() => _ProviderDemoWidget1State(); } class _ProviderDemoWidget1State extends State<ProviderDemoWidget1> { int _count = 0; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(providerDemoTitle1), ), body: CountProvider( count: _count, child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Builder( builder: (context2) { CountProvider provider = context2 .getElementForInheritedWidgetOfExactType<CountProvider>() .widget; return Text("计数:${provider.count}"); }, ), /// 读取和显示计数 RaisedButton( child: Text("increment"), onPressed: () => setState(() => _count++), ), Text(providerDemoIntroduction1), ], ), ), ), ); } } 复制代码
咱们先看效果图,咱们看到有三种场景。只有依赖的组件更新了UI。app
class CountModel extends ChangeNotifier { int count; CountModel(this.count); void increment() { count++; notifyListeners(); } } 复制代码
class Provider<T extends ChangeNotifier> extends InheritedWidget { final T model; Provider({Key key, this.model, Widget child}) : super(key: key, child: child); static T of<T extends ChangeNotifier>(BuildContext context, bool depend) { if (depend) { return context.dependOnInheritedWidgetOfExactType<Provider>().model; } else { Provider provider = context.getElementForInheritedWidgetOfExactType<Provider>().widget; return provider.model; } } @override bool updateShouldNotify(Provider old) { return true; } } 复制代码
class ChangeNotifierProvider<T extends ChangeNotifier> extends StatefulWidget { final Widget child; final T model; ChangeNotifierProvider({this.child, this.model}); @override _ChangeNotifierProviderState createState() => _ChangeNotifierProviderState(); } class _ChangeNotifierProviderState extends State<ChangeNotifierProvider> { _ChangeNotifierProviderState(); _update() { setState(() => {}); } @override void initState() { super.initState(); widget.model.addListener(_update); } @override void dispose() { super.dispose(); widget.model.removeListener(_update); } @override Widget build(BuildContext context) { return Provider( model: widget.model, child: widget.child, ); } } 复制代码
class ProviderDemoWidget3 extends StatefulWidget { ProviderDemoWidget3({Key key}) : super(key: key); @override _ProviderDemoWidget3State createState() => _ProviderDemoWidget3State(); } class _ProviderDemoWidget3State extends State<ProviderDemoWidget3> { CountModel _countModel = CountModel(0); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(providerDemoTitle3), ), body: ChangeNotifierProvider<CountModel>( model: _countModel, child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Builder(builder: (context1) { return Text( "计数:${Provider.of<CountModel>(context1, true).count}(有依赖状况)"); }), Builder(builder: (context2) { return Text( "计数:${Provider.of<CountModel>(context2, false).count}(无依赖状况)"); }), RaisedButton( child: Text("increment"), onPressed: () => _countModel.increment()), Text(providerDemoIntroduction3), ], ), ), ), ); } } 复制代码
上一个示例中CountModel不具备通用性,因此咱们写一个泛型版本ide
class Provider<T extends ChangeNotifier> extends InheritedWidget { final T model; Provider({Key key, this.model, Widget child}) : super(key: key, child: child); static T of<T extends ChangeNotifier>(BuildContext context, bool depend) { if (depend) { return context.dependOnInheritedWidgetOfExactType<Provider>().model; } else { Provider provider = context.getElementForInheritedWidgetOfExactType<Provider>().widget; return provider.model; } } @override bool updateShouldNotify(Provider old) { return true; } } 复制代码
class ChangeNotifierProvider<T extends ChangeNotifier> extends StatefulWidget { final Widget child; final T model; ChangeNotifierProvider({this.child, this.model}); @override _ChangeNotifierProviderState createState() => _ChangeNotifierProviderState(); } class _ChangeNotifierProviderState extends State<ChangeNotifierProvider> { _ChangeNotifierProviderState(); _update() { setState(() => {}); } @override void initState() { super.initState(); widget.model.addListener(_update); } @override void dispose() { super.dispose(); widget.model.removeListener(_update); } @override Widget build(BuildContext context) { return Provider( model: widget.model, child: widget.child, ); } } 复制代码
class CountModel extends ChangeNotifier { int count; CountModel(this.count); void increment() { count++; notifyListeners(); } } class ProviderDemoWidget3 extends StatefulWidget { ProviderDemoWidget3({Key key}) : super(key: key); @override _ProviderDemoWidget3State createState() => _ProviderDemoWidget3State(); } class _ProviderDemoWidget3State extends State<ProviderDemoWidget3> { CountModel _countModel = CountModel(0); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(providerDemoTitle3), ), body: ChangeNotifierProvider<CountModel>( model: _countModel, child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Builder(builder: (context1) { return Text( "计数:${Provider.of<CountModel>(context1, true).count}(有依赖状况)"); }), Builder(builder: (context2) { return Text( "计数:${Provider.of<CountModel>(context2, false).count}(无依赖状况)"); }), RaisedButton( child: Text("increment"), onPressed: () => _countModel.increment()), Text(providerDemoIntroduction3), ], ), ), ), ); } } 复制代码
咱们发现与上一个示例的简易版Provider上的使用方法是一致的。 正如介绍所描述的很是简单。固然了Provider库,可维护性,可测试性,可扩展性远比咱们所写的强大。oop
class ProviderDemoWidget4 extends StatefulWidget { ProviderDemoWidget4({Key key}) : super(key: key); @override _ProviderDemoWidget4State createState() => _ProviderDemoWidget4State(); } class _ProviderDemoWidget4State extends State<ProviderDemoWidget4> { CountModel _countModel = CountModel(0); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(providerDemoTitle4), ), body: ChangeNotifierProvider.value( value: _countModel, child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Consumer<CountModel>( builder: (contextC, model, child) { return Text("计数:${model.count}(有依赖状况)"); }, ), Builder(builder: (context2) { return Text( "计数:${Provider.of<CountModel>(context2, listen: false).count}(无依赖状况)"); }), RaisedButton( child: Text("increment"), onPressed: () => _countModel.increment()), Text(providerDemoIntroduction4), ], ), ), ), ); } } class CountModel extends ChangeNotifier { int count; CountModel(this.count); void increment() { count++; notifyListeners(); } } 复制代码
到此为止,咱们也就了解了Provider的基本原理和基本使用。 可咱们的征程才开始。知其然,更要知其因此然。接下来,咱们从setState开始一步步分析Provider状态管理的过程。