Flutter Provider 异步通信、Provider状态管理

1,323

题记 —— 执剑天涯,从你的点滴积累开始,所及之处,必精益求精。


Flutter是谷歌推出的最新的移动开发框架。

【x1】微信公众号的每日提醒 随时随记 每日积累 随心而过

【x2】各种系列的视频教程 免费开源 关注 你不会迷路

【x3】系列文章 百万 Demo 随时 复制粘贴 使用


在 Flutter 中可用于异步通信的方案有如下:


本文章实现的结果如下: 在这里插入图片描述


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 完整源码在这里

当然以小编的性格,肯定是要有视频录制的,目前正在录制中,你可以关注一下 西瓜视频 --- 早起的年轻人 随后会上传