题记
—— 执剑天涯,从你的点滴积累开始,所及之处,必精益求精。
Flutter是谷歌推出的最新的移动开发框架。
在 Flutter 中可用于异步通信的方案有如下:
-
Provider ( 就是本文了)
-
ValueNotifier 点击查看详情
-
Stream: StreamController的使用详情 | StreamBuilder组件的结合使用 | StreamBuilder 实现的倒计时进度圆圈
-
EventBus (不考虑使用)
本文章实现的结果如下:
1 前言
Provider 很多网友会说用于状态管理,在这里小编称为异步通信。
Provider 是一个组件也是一种编程思想,在使用 Provider 时首先要添加依赖:点击查看最新版本
dependencies:
provider: ^4.3.2+2
然后将依赖库拉取到本地
flutter packages get
provider 库中常用的组件有 ChangeNotifierProvider、MultiProvider、Provider、Consumer、Consumer2等等,后面会一一分析使用。
2 provider 的基本使用
第一步
就是在Flutter应用程序中提供一个 Provider 生产者,应用程序的整体可以是一个 Provider ,局部功能块也可以是单独的一个Provider,在这里,小编直接在根视图处理提供 ChangeNotifierProvider,如下代码清单1-1所示。完整源码在这里
///代码清单 1-1
///flutter应用程序中的入口函数
void main() => runApp(
ChangeNotifierProvider(
create: (BuildContext context) {
return TimeCounterModel();
},
child: ProviderMainApp(),
),
);
ChangeNotifierProvider 将数据事件处理源 TimeCounterModel 与 界面显示的UI结合在一起,TimeCounterModel 是我们自定义的ChangeNotifier,Widget页面负责发送事件与消费事件结果。
如一个网络请求,Widget页面发出网络请求的指令,具体的网络请求处理逻辑在 ChangeNotifier 中,然后处理好数据结果后再发送到 Widget 页面中通过 Consumer 将数据结果渲染显示在页面上。
第二步: TimeCounterModel 定义如下:
///代码清单1-2
import 'package:flutter/cupertino.dart';
import 'package:intl/intl.dart';
class TimeCounterModel with ChangeNotifier {
String _formatTime="00:00:00";
void getCurrentTime() {
///获取当前的时间
DateTime dateTime= DateTime.now();
///格式化时间 import 'package:intl/intl.dart';
///需要添加 intl 依赖
_formatTime = DateFormat("HH:mm:ss").format(dateTime);
notifyListeners();//2
}
get formatTime => _formatTime;//3
}
第三步
然后在 ProviderMainApp (当然外面还需要有一些嵌套,可以查看完整源码)这个页面中 定义了一个计时器 Timer 用来实现页面的时间按秒更新数据。
///代码清单1-3
class _TestABPageState extends State {
///计时器
Timer _timer;
@override
void initState() {
super.initState();
///间隔1秒执行时间
_timer = Timer.periodic(Duration(milliseconds: 1000), (timer) {
///发送事件
Provider.of<TimeCounterModel>(context,listen: false).getCurrentTime(); //2
});
}
@override
void dispose() {
super.dispose();
///取消计时器
_timer.cancel();
}
@override
Widget build(BuildContext context) {... ... }
}
在这里使用到了Provider发送数据,其实就是通过 Provider 结合 context 来获取TimeCounterModel的过程,获取到 TimeCounterModel 再调用其 getCurrentTime方法获取当前时间来触发时间更新。
TimeCounterModel model = Provider.of<TimeCounterModel>(context,listen: false);
然后就是 build 方法中定义的消费者,代码如下:
///代码清单1-4
/// 通过 Consumer 来消费事件结果
Widget buildBlocBuilder() {
return Consumer<TimeCounterModel>(
///参数 value 就是绑定的事件结果 TimeCounterModel
builder: (BuildContext context, value, Widget child) {
return Container(
///外边距
margin: EdgeInsets.only(left: 12, top: 12),
child: Text(
'${value.formatTime}',
style: TextStyle(fontSize: 22.0, color: Colors.red),
),
);
},
);
}
运行调试结果如下:
3 多数据源的巧妙操作
多数据源对应多个 ChangeNotifierProvider ,一个 Widget 页面同时需要绑定多个数据源的更新操作,每一个数据源都对应一个 ChangeNotifierProvider,在provider 框架中 通过 MultiProvider 来组合这些 ChangeNotifierProvider 代码如下:完整源码在这里
///代码清单2-1
class TestProviderMulPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
///组合多个Provider
return MultiProvider(
providers: [
///计时器
ChangeNotifierProvider(
create: (BuildContext context) {
return TimeCounterModel();
},
),
///随机数据
ChangeNotifierProvider(
create: (BuildContext context) {
return RandomNumberModel();
},
)
],
child: MaterialApp(
home: TestConsumerTimePage(),
),
);
}
}
然后在事件消费结果处理处可以分别使用 Consumer 来处理结果,代码如下:
@override
Widget build(BuildContext context) {
///页面主体脚手架
return Scaffold(
appBar: AppBar(
title: Text("Provider "),
),
body: Column(
children: [
buildTimeConsumer(),
buildNumberConsumer(),
],
),
);
}
/// 通过 Consumer 来消费事件结果
/// 计时器的更新
Widget buildTimeConsumer() {
return Consumer<TimeCounterModel>(
builder: (BuildContext context, value, Widget child) {
return Container(
///外边距
margin: EdgeInsets.only(left: 12, top: 12),
child: Text(
'当前时间 ${value.formatTime}',
style: TextStyle(fontSize: 22.0, color: Colors.red),
),
);
},
);
}
///随机数的更新
Widget buildNumberConsumer() {
return Consumer<RandomNumberModel>(
builder: (BuildContext context, value, Widget child) {
return Container(
///外边距
margin: EdgeInsets.only(left: 12, top: 12),
child: Text(
'回传的数据 ${value.randomNumber}',
style: TextStyle(fontSize: 22.0, color: Colors.red),
),
);
},
);
}
运行效果如下:
当然也可以通过 Consumer2 来组合同时监听这两个结果代码如下:完整源码在这里
///通过 Consumer2 来同时监听处理两个结果
Widget buildTimeConsumer2() {
return Consumer2<TimeCounterModel,RandomNumberModel>(
///参数 value 为 TimeCounterModel 类型
///参数 value2 为 RandomNumberModel 类型
builder: (BuildContext context, value,value2, Widget child) {
return Container(
///外边距
margin: EdgeInsets.only(left: 12, top: 12),
child: Text(
'当前时间 ${value.formatTime} 随机数 ${value2.randomNumber}',
style: TextStyle(fontSize: 22.0, color: Colors.red),
),
);
},
);
}
运行调试效果如下:
以小编的性格,要实现百万Demo随时复制粘贴肯定是需要源码的
MultiProvider 、Consumer2 完整源码在这里
ChangeNotifierProvider 、Consumer 完整源码在这里
当然以小编的性格,肯定是要有视频录制的,目前正在录制中,你可以关注一下 西瓜视频 — 早起的年轻人 随后会上传