了解和使用 Provider 进行 Flutter 状态管理
1. 为什么需要 Provider 来管理状态
对于数据变更和数据共享,Provider 是
- Flutter 的代码是
响应式/声明式
需要的。过去,Android/iOS 代码是绝对必要的
。 响应式
代码实际上需要状态管理
,也可以理解为数据共享
。接口和数据发生变化,因此需要对其进行管理。简单的
可以直接在StatefulWidget中进行管理。比较复杂的方式是使用Provider之类的来管理
。
简单和复杂数据的示例
数据的变化如何被认为是简单的? ——例如PageView组件中的当前页面、复杂动画中的当前进度、BottomNavigationBar中当前选定的选项卡。它们位于小部件树中,小部件树的其他部分不需要访问此状态。不需要反序列化这个状态,也不需要以复杂的方式改变。
Privider 应管理哪些数据更改? 例如,用户选项、登录详细信息、社交应用程序中的通知、电子商务应用程序中的购物车以及新闻应用程序中文章的已读/未读状态
。
.
.
Flutter 的状态管理包括 如果你一无所知,官方推荐绝对是你的首选。 嗯,官方推荐提供商。如果你不熟悉,可以先阅读这两篇文章。 provider官方文章 使用provider管理Flutter应用状态 使用provider只需3步即可轻松理解: 很简单~ . 代码如下: . 效果: 。大概就是这样。你可能会说你应该直接设置setState。不,绝对不一样,setState太不灵活了。 . 示例:在第 1 页设置一个值,然后将其显示在第 2 页(不要问为什么不直接使用 Navigator) , demo 演示,仅供演示) . .。 设置第 2 页上的值。返回第 1 页时,第 1 页将显示第 2 页的值 . .Redux
、Rx
、hooks 、
(例如单击按钮)。推荐使用Provider.of(context, Listen: false)来获取数据模型。 ScopedModel
和 Provider
等,其中Provider
官方推荐。 2. 使用提供商
2.1使用步骤
介绍provider
dependencies:
provider: ^3.1.0
复制代码
.
. 二. 2 最简单的例子 Provider.of(context) 方法
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter/foundation.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 创建 Widget 持有 CounterNotifier 数据
return ChangeNotifierProvider.value(
value: CounterNotifier(),
child: MaterialApp(
title: 'Privoder Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: ProvidePage(title: 'Provider 测试页面'),
),
);
}
}
class ProvidePage extends StatelessWidget {
final String title;
ProvidePage({Key key, this.title}) : super(key: key);
@override
Widget build(BuildContext context) {
// 获取 CounterNotifier 数据 (最简单的方式)
final counter = Provider.of<CounterNotifier>(context);
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'按下按钮,使数字增长:',
),
Text(
'${counter.count}',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
counter.increment();
},
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
// 核心:继承自ChangeNotifier
// 这种文件本来应该单独放在一个类文件连的
class CounterNotifier with ChangeNotifier {
int _count = 0;
int get count => _count;
increment() {
_count++;
// 核心方法,通知刷新UI,调用build方法
notifyListeners();
}
}
复制代码
.注意
.
.2.3 示例 Consumer 方法
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
main() {
runApp(ChangeNotifierProvider<CounterNotifier>.value(
value: CounterNotifier(),
child: MyApp(),
));
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return MultiProvider(
providers: [
Provider.value(value: 36),
ChangeNotifierProvider.value(value: CounterNotifier())
],
child: MaterialApp(
title: 'Privoder Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Page1(),
),
);
}
}
class Page1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
//获取文字大小
final size = Provider.of<int>(context).toDouble();
// 获取计数
final counter = Provider.of<CounterNotifier>(context);
// 调用 build 时输出
print('rebuild page 1');
return Scaffold(
appBar: AppBar(
title: Text('Page1'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// 显示计数
Text(
'Current count: ${counter.count}',
// 设置文字大小
style: TextStyle(
fontSize: size,
),
),
SizedBox(
height: 50,
),
// 跳转 Page2
RaisedButton(
onPressed: () => Navigator.of(context).push(
MaterialPageRoute(builder: (context) => Page2()),
),
child: Text('Next'),
),
],
),
),
);
}
}
class Page2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
print('rebuild page 2');
return Scaffold(
appBar: AppBar(
title: Text('Page2'),
),
body: Center(
child: Consumer2<CounterNotifier, int>(
builder: (context, counter, size, _) {
print('rebuild page 2 refresh count');
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'${counter.count}',
style: TextStyle(
fontSize: size.toDouble(),
),
),
],
);
}),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
// 不需要监听改变(listen: false 不会重新调用build)
Provider.of<CounterNotifier>(context, listen: false).increment();
},
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
class CounterNotifier with ChangeNotifier {
int _count = 0;
int get count => _count;
increment() {
_count++;
notifyListeners();
}
}
复制代码
注
.比较
作者:夏日舒适
链接:https://juejin.im/post/5d77bdf2518825513b537958
来源:掘金
版权归作者所有。商业转载请联系作者获得许可。非商业转载请注明出处。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。