Provider的几种使用方式
1、Provider
描述:是为恒定的数据提供的方法(类)。当一个widget只是从这个model中取数据,而不去监听数据的变化而去重绘界面.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class MyModel {
MyModel({this.counter = 0});
int counter = 0;
void incrementCounter() {
counter++;
print(counter);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
print("build方法来了");
return Provider(
create: (_) => MyModel(),
child: Scaffold(
appBar: AppBar(
title: Text('provider'),
),
body: Column(
children: <Widget>[
Builder(
builder: (context) {
// 获取到provider提供出来的值
MyModel _model = Provider.of<MyModel>(context, listen: false);
return Container(
margin: const EdgeInsets.only(top: 20),
width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.all(20),
alignment: Alignment.center,
color: Colors.lightBlueAccent,
child: Text('当前是:${_model.counter}'));
},
),
Consumer<MyModel>(
// 获取到provider提供出来的值
builder: (context, model, child) {
return Container(
margin: const EdgeInsets.only(top: 20),
width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.all(20),
alignment: Alignment.center,
color: Colors.lightGreen,
child: Text(
'${model.counter}',
),
);
},
),
Consumer<MyModel>(
// 获取到provider提供出来的值
builder: (context, model, child) {
return FlatButton(
color: Colors.tealAccent,
onPressed: model.incrementCounter,
child: Icon(Icons.add));
},
),
],
),
),
);
}
}
2、ListenableProvider和ChangeNotifierProvider
描述:当model对像中有数据变化时,需要触发widget中的元素重绘,实现数据驱动,这时我们需要用到ChangeNotifierProvider。
import 'package:flutter/material.dart';
import 'package:flutterproviderapp/detailPage.dart';
import 'package:provider/provider.dart';
import 'Models.dart';
class MyHomePage2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
print("MyHomePage2的build方法来了");
return ListenableProvider(
/* ListenableProvider和ChangeNotifierProvider几乎是一样的效果,只是ListenableProvider比ChangeNotifierProvider多了个_dispose函数,
会在适当的时候自动销毁,一般情况下只用changeNotifierProvider即可。
*/
create: (_) => MyModel(),
child: Scaffold(
appBar: AppBar(
title: Text('ChangeNotifierProvider'),
),
body: Column(
children: <Widget>[
Builder(
builder: (context) {
// 获取到provider提供出来的值
MyModel _model = Provider.of<MyModel>(context, listen: false);
return Container(
margin: const EdgeInsets.only(top: 20),
width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.all(20),
alignment: Alignment.center,
color: Colors.lightBlueAccent,
child: Text('当前是:${_model.counter}'));
},
),
Consumer<MyModel>(
// 获取到provider提供出来的值
child: Container(
// consumer 里的child的组件是不会被渲染的,builder里的组件是会被重新渲染的
margin: const EdgeInsets.only(top: 20),
width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.all(20),
alignment: Alignment.center,
color: Colors.lightGreen,
child: Text(
'hhhhhhhhhhh',
),
),
builder: (context, model, child) {
print("Consumer里的builder来了");
return Column(
children: <Widget>[
child!,
Container(
margin: const EdgeInsets.only(top: 20),
width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.all(20),
alignment: Alignment.center,
color: Colors.lightGreen,
child: Text(
'${model.counter}',
),
)
],
);
},
),
MyText(),
MyText2(),
Consumer<MyModel>(
// 获取到provider提供出来的值
builder: (context, model, child) {
return FlatButton(
color: Colors.tealAccent,
onPressed: model.incrementCounter,
child: Icon(Icons.add));
},
),
],
),
),
);
}
}
// 初始化一个单独的子部件套进去,看能不能用provider.of(context)获取model
class MyText extends StatelessWidget {
@override
Widget build(BuildContext context) {
print("MyText子部件的build方法来了");
MyModel _model =
Provider.of<MyModel>(context); // 这里的也能正常拿到Provider中的model的,因为是共享的。
return Container(
child: Text('当前是MyText里的:${_model.counter}'),
);
}
}
class MyText2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
print("MyText2子部件的build方法来了");
MyModel models =
Provider.of<MyModel>(context); // 这里的也能正常拿到Provider中的model的,因为是共享的。
return Container(
child: FlatButton(
color: Colors.tealAccent,
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return DiscoverDetailPage(models);
}));
},
child: Icon(Icons.ac_unit)),
);
}
}
例子中使用到的model
import 'package:flutter/material.dart';
class MyModel with ChangeNotifier {
MyModel({this.counter = 0});
int counter = 0;
void incrementCounter() {
counter++;
print(counter);
notifyListeners();
}
}
3、StreamProvider
描述:可以给StreamProvider提供一份初始的数据Model,通过给StreamProvider设置了一个每隔1秒更新一次的stream,ui上的计数值也是每隔一秒改变一次。
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class MyModel with ChangeNotifier {
MyModel({this.counter = 0});
int counter = 0;
void incrementCounter() {
counter++;
print(counter);
notifyListeners();
}
}
class MyHomePage4 extends StatelessWidget {
Stream<MyModel> getStreamProviderData(BuildContext context) {
print("getStreamProviderData方法");
return Stream<MyModel>.periodic(Duration(seconds: 1), getMyModel);
}
MyModel getMyModel(int count) {
print("getMyModel方法");
count++;
if (count > 60) {
return MyModel(counter: 60);
}else {
return MyModel(counter: count);
}
}
@override
Widget build(BuildContext context) {
print("build方法来了");
return StreamProvider(
initialData: MyModel(counter: 0),
create: getStreamProviderData, // 当这个函数执行的时候,会渲染UI
child: Scaffold(
appBar: AppBar(
title: Text('FutureProvider'),
),
body: Column(
children: <Widget>[
Builder(builder: (context) {
MyModel _model = Provider.of<MyModel>(context);
return Container(
margin: const EdgeInsets.only(top: 20),
width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.all(20),
alignment: Alignment.center,
color: Colors.lightBlueAccent,
child: Text('当前是:${_model.counter}'),
);
}),
Consumer<MyModel>(builder: (context, model, child) {
return Container(
margin: const EdgeInsets.only(top: 20),
width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.all(20),
alignment: Alignment.center,
color: Colors.lightGreen,
child: Text(
'${model.counter}',
),
);
}),
Consumer<MyModel>(builder: (context, model, child) {
return FlatButton(
color: Colors.tealAccent,
onPressed: model.incrementCounter,
child: Icon(Icons.add));
}),
],
),
));
}
}
4、MultiProvider
描述:可以组合Provider所提供的类,给Ui提供多个数据Model。
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class MyHomePage5 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<BannerModel>(create: (context) => BannerModel()),
ChangeNotifierProvider<ListModel>(create: (context) => ListModel()),
],
child: Scaffold(
appBar: AppBar(
title: Text('provider'),
),
body: Column(
children: <Widget>[
Builder(
builder: (context) {
BannerModel modol = Provider.of<BannerModel>(context);
return Container(
margin: const EdgeInsets.only(top: 20),
width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.all(20),
alignment: Alignment.center,
color: Colors.lightBlueAccent,
child: Text('当前Banner有几个:${modol.counter}'));
},
),
Consumer<ListModel>(
builder: (context, model, child) {
return Container(
margin: const EdgeInsets.only(top: 20),
width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.all(20),
alignment: Alignment.center,
color: Colors.lightGreen,
child: Text(
'当前Banner有几个:${model.counter}',
),
);
},
),
Consumer<BannerModel>(
builder: (context, model, child) {
return FlatButton(
color: Colors.tealAccent,
onPressed: model.getBanner,
child: Text("获取banner"));
},
),
Consumer<ListModel>(
builder: (context, model, child) {
return FlatButton(
color: Colors.tealAccent,
onPressed: model.getList,
child: Text("获取列表"));
},
),
],
),
),
);
}
}
class BannerModel with ChangeNotifier {
int counter = 0;
Future<void> getBanner() async {
await Future.delayed(Duration(microseconds: 500));
counter++;
notifyListeners();
print(counter);
}
}
class ListModel with ChangeNotifier {
int counter = 0;
Future<void> getList() async {
await Future.delayed(Duration(microseconds: 500));
counter++;
notifyListeners();
print(counter);
}
}
5、ProxyProvider
描述:当一个model依赖另一个model时,就以用ChangeNotifierProxyProvider把依赖的model推给被依赖model对像。当前例子模拟的是picmodel成功后,submitmodel才能成功。(场景:点击提交按钮的时候,先图片上传,成功了页面才提交成功)
import 'package:provider/provider.dart';
import 'package:flutter/material.dart';
class MyHomePage6 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<PicModel>(create: (context) => PicModel()),
ProxyProvider<PicModel, SubmitModel>(
update: (context, myModel, anotherModel) => SubmitModel(myModel),
),
],
child: Scaffold(
appBar: AppBar(
title: Text('provider'),
),
body: Column(
children: <Widget>[
Builder(
builder: (context) {
PicModel modol = Provider.of<PicModel>(context);
return Container(
margin: const EdgeInsets.only(top: 20),
width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.all(20),
alignment: Alignment.center,
color: Colors.lightBlueAccent,
child: Text('提交图片:${modol.counter}'));
},
),
Consumer<PicModel>(
builder: (context, model, child) {
return FlatButton(
color: Colors.tealAccent,
onPressed: model.upLoadPic,
child: Text("提交图片"));
},
),
Consumer<SubmitModel>(
builder: (context, model, child) {
return FlatButton(
color: Colors.tealAccent,
onPressed: () {
model.subMit().then((value) {
print("页面提交成功!");
});
},
child: Text("提交页面"));
},
),
],
),
),
);
}
}
class PicModel with ChangeNotifier {
int counter = 0;
Future<void> upLoadPic() async {
// counter++;
// notifyListeners();
await Future.delayed(Duration(seconds: 2));
counter++;
notifyListeners();
print(counter);
print("图片提交成功");
}
}
class SubmitModel {
PicModel _model;
SubmitModel(this._model);
Future<void> subMit() async {
await _model.upLoadPic();
}
}
点击下载demo
如果对您有用的话,点赞鼓励一下!
网友评论