flutter状态管理 provider使用
provider是flutter官方推荐的状态管理插件,是基于InheritedWidget实现的。
下面我们来讲一个provider的使用方法。
1.在pubspec.yaml
文件中添加 provider: ^6.1.2
开发文档:https://pub-web.flutter-io.cn/packages/provider 可以查看使用方法和最新版本号。
添加完成后,进行保存,VSCode会自动 flutter pub get
安装依赖,如果没有自动安装则手动执行flutter pub get
2..创建一个继承自ChangeNotifier的类 input_provider.dart
ChangeNotifier 是 Flutter SDK 中的一个简单的类。它用于向监听器发送通知。换言之,如果被定义为 ChangeNotifier,你可以订阅它的状态变化。(这和大家所熟悉的观察者模式相类似)。
import 'package:flutter/material.dart';
///监听内容变化
class InputProvider extends ChangeNotifier {
///等待改变的内容 可以是普通类型 也可以是 数组、字典、自定义model
String _inputText = '';
String get inputText => _inputText;
set inputText(String value) {
_inputText = value;
notifyListeners();
}
}
3.用MultiProvider包裹MyApp,让MyApp下的子孙节点具备监听状态改变的能力 main.dart
代码如下
import 'package:flutter/material.dart';
import 'one_page.dart';
import 'two_page.dart';
import 'package:provider/provider.dart';
import 'input_provider.dart';
void main() {
runApp(
// 使用MultiProvider包裹MyApp,使得MyApp下的子孙节点具备Provider的能力
MultiProvider(
providers: [
ChangeNotifierProvider<InputProvider>(
create: (context) => InputProvider()),
],
child: const MyApp(),
),
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
// 不显示debug
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
routes: {
'/one': (context) => const OnePage(),
'/two': (context) => const TwoPage(),
},
home: const OnePage());
}
}
4.新建 one_page.dart
:实现接收状态改变通知然后更新UI的方法 、 two_page.dart
:实现改变状态和更新UI的方法
one_page.dart
代码如下:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'input_provider.dart';
import 'two_page.dart';
class OnePage extends StatefulWidget {
const OnePage({super.key});
@override
State<OnePage> createState() => _OnePageState();
}
class _OnePageState extends State<OnePage> {
late String _text;
@override
void initState() {
_text = 'This is the first page';
//当文本发生变化时,监听变化内容,并更新文本
Provider.of<InputProvider>(context, listen: false).addListener(() {
String text =
Provider.of<InputProvider>(context, listen: false).inputText;
setState(() {
//刷新页面
_text = text;
});
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('One Page')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(_text),
ElevatedButton(
onPressed: () {
//跳转到第二个页面
// Navigator.pushNamed(context, '/two');
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const TwoPage(),
),
);
},
child: const Text('跳转第二个页面'),
),
]),
));
}
}
two_page.dart
代码如下:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'input_provider.dart';
class TwoPage extends StatefulWidget {
const TwoPage({super.key});
@override
State<TwoPage> createState() => _TwoPageState();
}
class _TwoPageState extends State<TwoPage> {
final TextEditingController _controller = TextEditingController();
late String _text;
@override
void initState() {
_text = 'This is the second page';
super.initState();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Two Page')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
//使用Consumer获取InputProvider中的inputText
Consumer(builder: (context, InputProvider provider, child) {
return Text(
provider.inputText.isEmpty ? _text : provider.inputText);
}),
//使用Consumer获取InputProvider中的inputText
Consumer(
builder: (context, InputProvider provider, child) => Text(
provider.inputText.isEmpty ? _text : provider.inputText)),
Container(
padding: const EdgeInsets.only(left: 15, right: 15),
child: TextField(
controller: _controller,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: '输入内容',
),
),
),
ElevatedButton(
onPressed: () {
_changeText();
},
child: const Text('提交改变'),
),
],
),
),
);
}
//给inputText赋值,触发监听事件
_changeText() {
Provider.of<InputProvider>(context, listen: false).inputText =
_controller.text;
}
}
当从TwoPage返回OnePage,再进入到TwoPage,我们会发现 TwoPage显示的还是我们修改过的内容,这是因为 inputText 已经改变,当再次进入的时候获取到的 provider.inputText
是有值的,会展示inputText的值而不是默认的 _text = 'This is the second page';