本文主要介绍flutter中状态管理组件provider,provider: ^6.0.3主要是用于我们系统InheritedWidge的封装,用于数据的传递和管理。
1. provider的使用
网上也有很多关于provider说明,也可以看下官方的provider的 README。这里我记录一下我自己学习。
我们对于简单的数据共享可以设置参数,之后子页面进行数据方法回调,从而完成数据间的通信。但是比较麻烦,下面我们看下我们使用provider如何达到这个效果。
我们2个页面使用同一个数据,在第二个页面使用点击增加方法。之后返回在第一个页面也显示出增加后的数据count达到同步的效果。
点击增加
看下代码实现首先是使用StatelessWidget来显示页面,简单的页面跳转就不展示了。我们定义一个model用来存储我们的count,我么混入通过混入 ChangeNotifier 管理监听者(通知模式)。我们写读数据,并且当数据发生改变的时候,使用通知更新数据。
class CountModel with ChangeNotifier { int _count = 0; // 读方法 int get counter => _count; // 写方法 void increment() { _count++; notifyListeners(); // 通知监听者刷新 } }
我们2个页面都要使用这个数据,我们要把这个数据放在这2个子页面的父节点上。通过 Provider 组件封装数据资源,value就是需要共享的数据资源
class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { // 通过 Provider 组件封装数据资源 return ChangeNotifierProvider.value( value: CountModel(), // 需要共享的数据资源 child: MaterialApp( home: FirstPage(), )); } }
我们在页面使用的地方进行取数据
final _counter = Provider.of<CountModel>(context);
上下文就包含了我们父节点中设置的value 即CountModel()。
// 第一个页面 class FirstPage extends StatelessWidget { @override Widget build(BuildContext context) { // 取出数据 final _counter = Provider.of<CountModel>(context); return Scaffold( appBar: AppBar( title: const Text('第一个页面'), ), body: Center( child: Text('第一个页面count:${_counter.counter}'), ), // 跳转到 SecondPage floatingActionButton: FloatingActionButton( child: const Icon(Icons.next_plan), onPressed: () => Navigator.of(context) .push(MaterialPageRoute(builder: (context) => SecondPage())))); } } // 第二个页面 class SecondPage extends StatelessWidget { @override Widget build(BuildContext context) { // 取出数据 final _counter = Provider.of<CountModel>(context); return Scaffold( appBar: AppBar( title: const Text('第二个页面'), ), // 展示资源中的数据 body: Center( child: Text('第二个页面count:${_counter.counter}'), ), floatingActionButton: FloatingActionButton( onPressed: _counter.increment, child: const Icon(Icons.add), ), ); } }
通过provider很简单的达到了我们的数据共享,同时通过通知让我们的页面进行了刷新。
2. 控制Widget的刷新颗粒度
我们上面的页面中涉及的Widget变化也就是一个文字的展示,没有必要整个页面都刷新,这样可以提高我们的性能。
我们把我们Icon换成自定义的,可以发现当我们点击的时候就会一直重新build,实际我们不需要他们变化,那么我们只要我们那个Widget使用了数据,我们刷新该Widget即可。我们就要使用Consumer
final Widget Function( BuildContext context, T value, Widget? child, ) builder;
定义child为我们包裹的widget,T为我们model的类型。
body: Center( child: Consumer<CountModel>( builder: (context,CountModel counter,_) => Text('第二个页面count:${counter.counter}'), ), ),
这里我们的child为空直接每次刷新Consumer的Widget。那么我们的button怎么刷新呢
floatingActionButton: Consumer<CountModel>( builder: (context, CountModel counter, child) => FloatingActionButton( onPressed: counter.increment, child: child, ), child: MyIcon(), )
这里我们使用child属性,把我们的builder隔离开,这样我们就可以是我们的数据和视图做到隔离效果。
3. 小结
对于数据共享和数据传递provider组件确实提供了我们快捷的方式,我们在使用的过程中要注意provider组件位于父节点位置,这样子节点才能共享数据状态,其次我们尽可能的减少我们刷新的颗粒度,最好在使用数据的地方进行刷新组件。
以上就是flutter状态管理Provider的使用学习的详细内容,更多关于flutter状态管理Provider的资料请关注好代码网其它相关文章!