Flutter利用第三方的Provider来状态管理,对新手而言相对容易一点,这里介绍通过Provider来改变APP的主题色,示例程序做得非常简单,主要帮助区理解和熟悉Provider的使用.
依赖库 provider: ^4.0.2
导入类 import ‘package:provider/provider.dart’;
用于管理主题颜色的状态等MaterialApp级别的应用场景
用with类型的ChangeNotifier 建立需监管的数据类
class Counter with ChangeNotifier {
int _count = 1; 和ScopedModel相似,分离数据继承ChangeNotifer
Color _themeColor = Colors.redAccent;
int get value => _count;
Color get themeColor => _themeColor;
void addValue() { _count++; notifyListeners(); }
Color changeThemeColor({Color color: Colors.teal}) {
_themeColor = color; notifyListeners();
return _themeColor; }} void可以不用返回
用MultiProvider来包裹MaterialApp
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
Color _themeColor;
return MultiProvider( //放置监控
providers: [ChangeNotifierProvider(create: (_) => Counter())], //数据绑定
child: Consumer( //数据展示
builder: (BuildContext context, Counter counter, Widget child) {
_themeColor = counter.themeColor;
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: _themeColor, ),
home: MyHome(), ); }), ); }}
providers: [ ChangeNotifierProvider(create: (_) => Counter(), ) ],
展示的方式1
Counter counter = Provider.of(context); //提前获取Counter实例
Provider.of(context).value //引起整个页面的重绘,可以用上面counter.value
Provider.of(context, listen: false).addValue();
Provider数据展示和InheritedWidget有点类似,
也可以用Consumer来展示数据和ScopedModel类似
除了像上一步中使用Consumer可以获取到当前的model数据之外,还可以使用Provider.of;
但是使用Provider.of,默认使用时,Model中的 notifyListeners() 被调用后,所有这个Model关联的Consumer的build方法都会被调用,也就是会刷新相关联的Widget;
展示方式2
可用Consumer来包裹某个Widget来
Consumer( //可作为组件来用返回Widget ,是build方法
builder: (BuildContext context,Counter counter,Widget child){ //Counter为
return Text("通过consumer获取的值:${counter.value}"); },) //只重绘这个
和ScopedModelDescendant差不多
ScopedModelDescendant( //用这个区包裹需要变化管理的Widget
builder: (context,_,model)=>ActionChip(
label: Text("${model.count}"),
onPressed: (){model.addCount();}, ), )
将Consumer包裹在MaterialApp上,数据展示在MaterialApp上的变化,这个也就是Provider在程序入口级别的应用场景
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
Color _themeColor;
return MultiProvider( //放置监控
providers: [ChangeNotifierProvider(create: (_) => Counter())], //数据绑定
child: Consumer( //数据展示
builder: (BuildContext context, Counter counter, Widget child) {
_themeColor = counter.themeColor;
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: _themeColor, ),
home: MyHome(), ); }), ); }}
下面的代码通过测试,在yaml文件中添加依赖,拷贝下面代码后粘贴即可执行使用,第一次运行比较慢,请耐心等待!
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter/services.dart';
void main() {
runApp(MyApp());
SystemUiOverlayStyle systemUiOverlayStyle =
SystemUiOverlayStyle(statusBarColor: Colors.transparent);
SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle); //让状态栏变成透明
}
class Counter with ChangeNotifier {
int _count = 1;
Color _themeColor = Colors.redAccent;
int get value => _count;
Color get themeColor => _themeColor;
void addValue() {
_count++;
notifyListeners();
}
Color changeThemeColor({Color color: Colors.teal}) {
_themeColor = color;
notifyListeners();
return _themeColor;
}
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
Color _themeColor;
return MultiProvider(
providers: [ChangeNotifierProvider(create: (_) => Counter())],
child: Consumer(
builder: (BuildContext context, Counter counter, Widget child) {
_themeColor = counter.themeColor;
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: _themeColor,
),
home: MyHome(),
);
}),
);
}
}
class MyHome extends StatefulWidget {
@override
_MyHomeState createState() => _MyHomeState();
}
class _MyHomeState extends State {
//Counter _counter = new Counter();
@override
Widget build(BuildContext context) {
print('页面重绘了。。。。。。。。。。。');
return Scaffold(
appBar: PreferredSize( //用PreferredSize来调整AppBar的高度
preferredSize: Size.fromHeight(30),
child: AppBar(
title: Text("入口级别的Provider演示${Provider.of(context).value}"),
centerTitle: true,
),
),
body: Container(
width: double.infinity,
margin: EdgeInsets.all(10),
child: Column(
//mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Consumer(builder:
(BuildContext context, Counter icounter, Widget child) {
return Text(
//"无",
"通过Provider.of获取值:${Provider.of(context).value}", //没有用consumer包裹的不会自动更新,只有页面重绘时才被更新
style: TextStyle(fontSize: 20),
);
}),
SizedBox(
height: 10,
),
RaisedButton(
color: Colors.blue[200],
child: Icon(Icons.add),
onPressed: () {
print("add");
Provider.of(context, listen: false)
.addValue(); //页面级别的使用这个,方法里有notifyListeners();
},
),
SizedBox(
height: 10,
),
Consumer(
builder: (BuildContext context, Counter counter, Widget child) {
return Text("通过consumer获取的值:${counter.value}",
style: TextStyle(fontSize: 20));
},
),
SizedBox(
height: 10,
),
RaisedButton(
color: Colors.green,
child: Text("主题色变成按钮的颜色"),
onPressed: () {
Provider.of(context, listen: false)
.changeThemeColor(color: Colors.green);
},
),
SizedBox(
height: 10,
),
RaisedButton(
color: Colors.orangeAccent,
child: Text("主题颜色变成按钮的颜色"),
onPressed: () {
Provider.of(context, listen: false)
.changeThemeColor(color: Colors.orangeAccent);
},
),
],
),
),
);
}
}