Flutter 知识集锦 | 监听与通知 ChangeNotifier

这篇具有很好参考价值的文章主要介绍了Flutter 知识集锦 | 监听与通知 ChangeNotifier。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


theme: cyanosis

1. 数据的提供者与消费者

今天想要和大家好好聊聊 ChangeNotifier 这个东西,从名字上来看它由 change(改变)Notifier(通知器) 构成。打个比方:

有三个铁粉跟我说: "你发新文章的时候跟我说一声"。
之后我发布文章后,分享给了他们三个人。

很明显,这是一个 发布-订阅 模式,其中:

发布者是博主,是数据的提供者,也是通知事件的执行人。
订阅者是粉丝,是数据的消费者,需要依赖数据完成需求。

Flutter 知识集锦 | 监听与通知 ChangeNotifier,flutter,java,前端,javascript,开发语言

所以 ChangeNotifier 的角色很明显,他的职责是:在数据变化时,触发通知的动作。在整个过程中,发布者和订阅者是一对多的关系。所以对于通知器来说,需要维护一个列表通知订阅者。


在实际开发中,有很多类似的场景。比如不同界面中有若干个组件期望得到下载的进度数据,来完成自身的视觉表现。这里 下载进度 就是核心的数据,组件 相当于订阅者,需要感知数据的变化,完成展示需求。而发布者就是 下载进度数据的 提供者

| 案例演示 | 监听-通知关系 | | --- | --- | | Flutter 知识集锦 | 监听与通知 ChangeNotifier,flutter,java,前端,javascript,开发语言 | Flutter 知识集锦 | 监听与通知 ChangeNotifier,flutter,java,前端,javascript,开发语言 |


2. 通过一个小案例了解 ChangeNotifier 的使用

下面,我们来完成上面下载进度的模拟案例,演示一下 ChangeNotifier 的使用。首先来分析一下:
在视图方面,主页面中有一个圆形的进度条 HomeProgressView 组件;点击头部栏左上角进入详情页,其中有一个矩形的进度条 DetailProgressView 组件。
在视图方面,主界面右下角按钮点击时,进度数据将会不断增加,直到 1 ;两个进度相关的组件,需要感知进度数值的变化,从而更新进度呈现。

这里只给出核心的代码,案例的完全代码已集成到 FlutterUnit,可以在仓库中自己查看 changenotifier01~

Flutter 知识集锦 | 监听与通知 ChangeNotifier,flutter,java,前端,javascript,开发语言


  • 数据方面处理

由于 ChangeNotifier 是一个混入类,无法直接实例化,使用时需要被混入来发挥效力。如下所示,这里定义 ProgressValueNotifier 类混入 ChangeNotifier。进度数据是一个 double 类型的浮点数,维护在 ProgressValueNotifier 中。

数据变化的时机就是 _value 改变时,在 set 方法中更新 _value 的值,并通过 notifyListeners 方法通知监听者数据已经变化,从而让订阅者们可以感知变化,并做出响应。

```dart ProgressValueNotifier progress = ProgressValueNotifier(); /// tag1

class ProgressValueNotifier with ChangeNotifier{

double _value = 0;

double get value =>_value;

String get valueStr => '${(value*100).toStringAsFixed(1)}%';

set value(double value){ _value = value.clamp(0, 1); notifyListeners(); } } ```

注 - tag1 : 这里为了方便访问 ProgressValueNotifier 对象,先将 progress 对象作为全局变量。后续文章会继续探讨对该对象的维护方式。


这里通过 Timer.periodic 开启一个 200 ms 的周期回调,触发 _updateProgress 方法。回调方法中,每次触发增加 1% 的进度,以此模拟下载进度数值的增加。

```dart ---->[page/home/home_page.dart]---- Timer? _timer;

void startTimer(){ if(timer!=null) return; if(progress.value==1.0){ progress.value=0; } timer = Timer.periodic(const Duration(milliseconds: 200),updateProgress); }

void _updateProgress(Timer timer) { if(progress.value>=1.0){ timer.cancel(); _timer = null; return; } progress.value += 0.01; } ```


  • 视图方面处理

详情页的进度和主页的进度视图上的处理是基本类似的,这里只拿 DetailProgressView 来说明一下。如下代码所示,主要需要处理三个部分:

[1]. 通过 ChangeNotifier 对象的 addListener 方法添加订阅关系。
[2]. 被加入回调的函数,将会在发布通知时触发。其中可以处理 更新逻辑
[3]. 在状态类销毁后,要及时移除监听。否则仍会在销毁后,触发更新,导致异常。

```dart class DetailProgressView extends StatefulWidget {

const DetailProgressView({super.key});

@override State createState() => _DetailProgressViewState(); }

class _DetailProgressViewState extends State {

@override void initState() { super.initState(); /// 1. 添加监听 - 订阅 progress.addListener(_update); }

@override Widget build(BuildContext context) { return Stack( alignment: Alignment.center, children:[ SizedBox( width: 200, height: 50, child: LinearProgressIndicator( value: progress.value, backgroundColor: Colors.grey, ), ), Text(progress.valueStr,style: TextStyle(color: Colors.white),) ], ); }

/// 2. 发布通知时,触发更新 void _update() { setState(() {}); }

@override void dispose() { /// 3. 组件销毁时,移除监听 progress.removeListener(_update); super.dispose(); } } ```

这样 ChangeNotifier 使用的一个小案例就介绍完了。大家可以自己在 FlutterUnit 中跑一跑,体验一下。下面来从源码的角度来分析一下 ChangeNotifier 的实现细节。


3. ChangeNotifier 源码分析

ChangeNotifier 类源码位于: flutter\lib\src\foundation\change_notifier.dart
首先,它是一个 mixin,说明该类型无法直接实例化对象 (混入类无构造函数)。其次,它实现了 Listenable 接口。

Flutter 知识集锦 | 监听与通知 ChangeNotifier,flutter,java,前端,javascript,开发语言

Listenable 是可监听对象的顶层接口,定义了 addListenerremoveListener 两个抽象方法。

```dart abstract class Listenable { const Listenable(); factory Listenable.merge(List listenables) = _MergingListenable;

void addListener(VoidCallback listener);

void removeListener(VoidCallback listener); } ```

ChangeNotifier 既然实现了 Listenable 接口,那自然核心任务是实现抽象方法的具体逻辑。下面是 ChangeNotifier 类的结构,其中核心是维护了 List<VoidCallback?> 类型的 _listeners 对象,作为一种订阅关系。

Flutter 知识集锦 | 监听与通知 ChangeNotifier,flutter,java,前端,javascript,开发语言


下面是添加监听的实现,调试中是详情页进入的时刻。在 addListener 处理完毕后,更新的回调函数将会被加入到 _listeners 回调列表中。

Flutter 知识集锦 | 监听与通知 ChangeNotifier,flutter,java,前端,javascript,开发语言

dart @override void addListener(VoidCallback listener) { if (_count == _listeners.length) { if (_count == 0) { _listeners = List<VoidCallback?>.filled(1, null); } else { final List<VoidCallback?> newListeners = List<VoidCallback?>.filled(_listeners.length * 2, null); for (int i = 0; i < _count; i++) { newListeners[i] = _listeners[i]; } _listeners = newListeners; } } _listeners[_count++] = listener; }

ChangeNotifier#notifyListeners 方法中,将会变量 _count 次,触发 _listeners 列表对应索引的的回调函数。这就是通过函数对象,实现的添加监听和触发通知的一种机制。

Flutter 知识集锦 | 监听与通知 ChangeNotifier,flutter,java,前端,javascript,开发语言


4. ChangeNotifier 和 ValueNotifier

了解 ChangeNotifier 的使用之后,就非常好理解 ValueNotifier 。它支持一个泛型,继承自 ChangeNotifier ,实现 ValueListenable 接口。使用它可以监听某种特定类型的数据,从实现逻辑上来看就是在 set 时触发 notifyListeners 而言,也没有什么神奇的东西。

```dart class ValueNotifier extends ChangeNotifier implements ValueListenable { ValueNotifier(this._value) { /// 略... }

@override T get value => value; T _value; set value(T newValue) { if (value == newValue) { return; } _value = newValue; notifyListeners(); }

@override String toString() => '${describeIdentity(this)}($value)'; } ```


总的来说 ChangeNotifier 提供了一个 添加监听 - 发布通知 的机制,对于单类型的数据有 ValueNotifier 派生类方便使用。对于多种类型的数据,或者触发监听时机希望灵活控制时,可以自己混入 ChangeNotifier 来处理。可监听对象对于 Flutter 而言是一个非常重要的存在, ChangeNotifier 只是其中非常重要的一支。

我们平时使用的 TabControllerScrollControllerTextEditingControllerFocusNode 等;另外,滑动机制中,手势事件产生的数据和视口感知的滑动偏移量,通过 ScrollPosition 来连接。它们都是 ChangeNotifier 的派生类,足以见得 ChangeNotifier 在 Flutter 中的分量。

那本文就到这了,后续还会带来更多的精彩内容,下次再见~文章来源地址https://www.toymoban.com/news/detail-723906.html

到了这里,关于Flutter 知识集锦 | 监听与通知 ChangeNotifier的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Flutter Notification (通知)

    通知可以用来监听事件,用来刷新页面,先看通知的源码: 从源码可以看出,一般使用方式需要先创建一个继承自 Notification 的类,例如: 使用 NotificationListenerMyNotification() , onNotification 是一个通知回调,其中有个参数 notification ,也就是 MyNotification 的实例对象: 在子组件

    2024年02月16日
    浏览(64)
  • MQTT EMQX v5.0版本监听客户端上下线通知、认证、授权

    之前在自助洗车项目中使用emqx的是4.4版本,最新部署的时候采用了5.0。 旧版本认证、上下线通知等都需要开启插件,在配置文件修改,操作比较麻烦。 升级后增强了dashboard(web管理界面),好多插件都成为内置插件,无需开启,且很多操作无需进入配置文件,直接在web即可

    2024年02月09日
    浏览(37)
  • ZooKeeper源码解析——学习ApacheZookeeper原理,掌握其核心组件的数据模型、监听通知机制等

    作者:禅与计算机程序设计艺术 随着互联网的飞速发展,各种信息数据越来越多,数据的存储也越来越依赖于分布式文件系统或NoSQL数据库。而传统的单机数据库往往不具备弹性可扩展性和高可用容错能力,在面对海量数据时难免会遇到性能瓶颈。为了解决这一问题,人们又

    2024年02月10日
    浏览(27)
  • Spark相关知识点(期末复习集锦)

    嗨喽,最近小伙伴们快要期末考试了吧,下面是我对《Spark零基础实战》的总结,希望能帮助到你们。 Spark,拥有hadoop MR所具有的优点,但不同于MR的是job中监测结果可以 保存在内存中 ,从而不再需要读写HDFS,因此spark能够更好的适用于数据挖掘与机器学习等需要迭代的m r的

    2024年02月02日
    浏览(37)
  • Flutter ValueNotifier 监听数据变化

    系统提供了 ValueNotifier 组件的实现数据监听,局部刷新: 监听数据: 更新数据:

    2024年02月16日
    浏览(25)
  • flutter 调出键盘和监听输入

    调出键盘: 监听按键: 完整代码

    2024年02月10日
    浏览(33)
  • flutter监听键盘输入做出反应

    2024年02月10日
    浏览(33)
  • 软考系统架构师知识点集锦七:计算机系统基础知识

    2.1.1计算机系统组成 2.1.2 存储系统          时间局部性 :指程序中的某条指令一旦执行,不久以后该指令可能再次执行,典型原因是由于程序中存在着大量的循环操作。          空间局部性 :指一旦程序访问了某个存储单元,不久以后,其附近的存储单元也将被访问,

    2024年02月06日
    浏览(36)
  • Flutter对象状态动态监听Watcher

      场景:当一个表单需要在表单全部或者特定项赋值后才会让提交按钮可点击。   1.普通实现方式:   2.使用Watcher方式实现:  logcat输出: 方式1和方式2都能达到效果,但是方式1需要对每一个变量进行监听,在每一个赋值的地方得检查所有得值是否都已有了值,这样实现的

    2024年02月11日
    浏览(25)
  • 软考系统架构师知识点集锦九:数据库系统

    2.1.1数据库模式 (1)三级模式:外模式对应视图,模式(也称为概念模式)对应数据库表,内模式对应物理文件。 (2)两层映像:外模式-模式映像,模式-内模式映像;两层映像可以保证数据库中的数据具有较高的逻辑独立性和物理独立性。 (3)物理独立性:即数据库的内模式发生改变时,

    2024年02月07日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包