flutter状态管理案例
FLUTTER项目中管理不同组件、不同页面之间共享的数据关系。当需要共享的数据关系达到几十上百个的时候,我们就很难保持清晰的数据流动方向和顺序了,导致应用内各种数据传递嵌套和回调满天飞。在这个时候,我们迫切需要一个解决方案,来帮助我们理清楚这些共享数据的关系,于是状态管理框架便应运而生。
下面来了解一下如何使用Provider进行状态管理,使用步骤如下:
1、首先安装Provider flutter pub get
dependencies: flutter: sdk: flutter provider: 6.0 #provider依赖
2、将需要共享的状态进行封装 就是类封装
//定义需要共享的数据模型,通过混入ChangeNotifier管理听众 class CounterModel with ChangeNotifier { int _count = 0; //读方法 int get counter => _count; //写方法 void increment() { _count++; notifyListeners();//通知听众刷新 } }
这个类需要混入ChangeNotifier。这个类能够帮助我们管理所有依赖资源封装类的听众。当资源封装类调用 notifyListeners 时,它会通知所有听众进行刷新。
3、将封装的状态放在组件最高层,因为 Provider 实际上是 InheritedWidget 的语法糖,所以通过 Provider 传递的数据从数据流动方向来看,是由父到子(或者反过来),所以一般就是把资源放到更高的层级。需要注意的是是如何放。
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { //通过Provider组件封装数据资源 return ChangeNotifierProvider.value( value: CounterModel(),//需要共享的数据资源 child: MaterialApp( home: FirstPage(), ) ); } }
因为 provider 是一个 Widget。所以,我们直接在 MaterialApp 的外层使用 Provider 进行包装,就可以把数据资源依赖注入到应用中,这里需要注意的是,由于封装的数据资源不仅需要为子 Widget 提供读的能力,还要提供写的能力,因此我们需要使用 Provider 的升级版 ChangeNotifierProvider。而如果只需要为子 Widget 提供读能力,直接使用 Provider 即可。
4、在子组件中通过of方法获取属性与方法,部署状态。
//第一个页面,负责读数据 class FirstPage extends StatelessWidget { @override Widget build(BuildContext context) { //取出资源 final _counter = Provider.of<CounterModel>(context); return Scaffold( //展示资源中的数据 body: Text('Counter: ${_counter.counter}'), //跳转到SecondPage floatingActionButton: FloatingActionButton( onPressed: () => Navigator.of(context).push(MaterialPageRoute(builder: (context) => SecondPage())) )); } } //第二个页面,负责读写数据 class SecondPage extends StatelessWidget { @override Widget build(BuildContext context) { //取出资源 final _counter = Provider.of<CounterModel>(context); return Scaffold( //展示资源中的数据 body: Text('Counter: ${_counter.counter}'), //用资源更新方法来设置按钮点击回调 floatingActionButton:FloatingActionButton( onPressed: _counter.increment, child: Icon(Icons.add), )); } }
另一个例子
import 'package:flutter/material.dart'; class Datashare extends StatelessWidget { @override Widget build(BuildContext context) { return Row( children: [App1(), App2()], ); } } class App1 extends StatelessWidget { // 获取属性与方法 @override Widget build(BuildContext context) { return Container( width: 100, height: 100, color: Colors.yellow, child: Text("111"), ); } } class App2 extends StatelessWidget { // 获取属性与方法 @override Widget build(BuildContext context) { return Container( width: 100, height: 100, color: Colors.redAccent, child: FlatButton(child: Text("加一"),color: Colors.redAccent,onPressed: ()=>{ }) ); } }
改造成支持provider 的代码
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; // 封装状态: class CountContainer with ChangeNotifier { int _count = 0; int get counter => _count; void increment() { _count++; notifyListeners(); } } // class Datashare extends StatelessWidget { // @override // Widget build(BuildContext context) { // return Row( // children: [App1(), App2()], // ); // } // } // 将封装的装填放到顶层组件; class Datashare extends StatelessWidget { @override Widget build(BuildContext context) { return ChangeNotifierProvider.value( value: CountContainer(), child: Row( children: [App1(), App2()], )); } } class App1 extends StatelessWidget { // 获取属性与方法 @override Widget build(BuildContext context) { final _counter = Provider.of<CountContainer>(context); print(_counter); return Container( width: 100, height: 100, color: Colors.yellow, child: Text('${_counter._count}'), ); } } class App2 extends StatelessWidget { // 获取属性与方法 @override Widget build(BuildContext context) { final _counter = Provider.of<CountContainer>(context); return Container( width: 100, height: 100, color: Colors.redAccent, child: FlatButton( child: Text("加一"), color: Colors.redAccent, onPressed: () => { _counter.increment() })); } }
5、多个状态 共享
数据状态的共享。
此时我么需要MultiProvider,我们修改上面的代码,注入一个只读的数字,这个数字只做展示,局部代码如下
class Datashare extends StatelessWidget { @override Widget build(BuildContext context) { return MultiProvider(providers: [ Provider.value(value: 30.0), ChangeNotifierProvider.value( value: CountContainer(), ) ], child: Row( children: [App1(), App2()], )); } } class App1 extends StatelessWidget { // 获取属性与方法 @override Widget build(BuildContext context) { final _counter = Provider.of<CountContainer>(context); final textSize = Provider.of<double>(context); print(_counter); return Container( width: 100, height: 100, color: Colors.yellow, child: Text('${_counter._count}----$textSize'), ); } }