前言:如页面A和页面B都需要数据Name,如果定义为全局变量,但当在B页面中修改后还需要手动通知A页面进行更新,增加维护成本和出错率。本文介绍通过Provider将数据和Widget进行关联,之后更新数据则相关联的Widget自动刷新。类似Android的DataBinding。
正文:
1、添加Provider依赖
provider: ^3.0.0
2、定义有状态的数据(只需继承ChangeNotifier,并在set方法中添加notifyListeners()即可)
import 'package:flutter/foundation.dart';
class NameModel with ChangeNotifier{
String _name = "未知";
set name(String name){
_name = name;
notifyListeners();
}
String get name{
return _name;
}
}
3、关联Widget(页面A和页面B需要该数据,则将数据关联至页面A和页面B的父Widget。Provider提供的是子孙Widget间的数据共享的能力)
(1)父widget通过ChangeNotifierProvider提供数据。若需要提供多个状态,可以放到MultiProvider里。
(2)子页面通过Consumer获取和监听数据。
4、通过Provider.of<T>(context)更新数据。如只想更新数据不更新UI,则使用Provider.of<T>(context, listen: false)
import 'package:flutter/material.dart';
import 'package:flutterapp/NameModel.dart';
import 'package:provider/provider.dart';
import 'package:flutterapp/PagerOne.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
builder: (context) => NameModel(),
child: MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(title: 'Flutter Demo Home Page'),
),
);
}
}
class MyHomePage extends StatelessWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Column(
children: [
Consumer<NameModel>(
builder: (context, nameNotifier, child) {
return Text(
'name=${nameNotifier.name}',
);
},
),
FlatButton(
onPressed: () {
Provider.of<NameModel>(context).name = "张三";
},
child: Text(
'修改',
),
),
FlatButton(
onPressed: () {
Navigator.push(context, MaterialPageRoute(
builder: (context) {
return PagerOne();
},
));
},
child: Text(
'跳转',
),
),
],
),
);
}
}
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutterapp/NameModel.dart';
import 'package:provider/provider.dart';
class PagerOne extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Pager One"),
),
body: Column(
children: [
MyText(),
FlatButton(
onPressed: () {
Provider.of<NameModel>(context).name = "李四";
},
child: Text(
'修改',
),
),
],
));
}
}
class MyText extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<NameModel>(
builder: (context, nameNotifier, child) {
return Text(
'name=${nameNotifier.name}',
);
},
);
}
}
注:Consumer尽可能放到低层,只包含需要更新的widget