Flutter状态管理系列之InheritedWidget,Notifcation,eventbus的使用和原理

本文主要是介绍Flutter状态管理系列之InheritedWidget,Notifcation,eventbus的使用和原理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录
InheritedWidget
示例
构造函数传值:
继承 InheritedWidget 传值:
Notification
示例
EventBus
示例
示例完整源码
Flutter是由众多widget构成的UI框架,之前的文章我们在不同的widget之间传递数据是通过构造函数传参的方式传递。如果嵌套的widget过多,这么写不免有些麻烦且层级复杂。所以Flutter还提供了其他方案来实现跨 widget 间数据的传递,下面就介绍InheritedWidget、Notification 和 EventBus这三种方案。

InheritedWidget
InheritedWidget 是widget的基类,可有效地向下传播信息。
可以理解为子 widget可以在任何位置获取继承了InheritedWidget的父 widget中的数据。

示例
示例中通过构造函数和继承InheritedWidget两种方式实现父 widget :FrogColor向子 widget:FColor传值。

构造函数传值:


继承 InheritedWidget 传值:
首先定义一个类FrogColor继承InheritedWidget,并在构造方法中传递数据和方法:model 和 doSomeThing
class FrogColor extends InheritedWidget {

  const FrogColor({
    Key key,
    @required this.model,
    @required this.doSomeThing,
    @required Widget child,
  }) : assert(model != null),
        assert(child != null),
        super(key: key, child: child);

  // 直接从 _FirstPageState 中的 State 获取数据,这里可指定为泛型
  final _FirstPageState model;
  // 方法
  final Function() doSomeThing;

  // 获取实例
  static FrogColor of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<FrogColor>();
  }

  // 判断是否需要更新
  @override
  bool updateShouldNotify(FrogColor old) => model != old.model;
}

在布局中使用FrogColor包裹FColor子widget,同时传递data和 doSomeThing 方法。由于上面定义的data是_FirstPageState所以这里直接传递this,doSomeThing方法中我们传递了_changeColor用于改变mColor的值,并且在子布局中能够刷新显示最新的color。

最后我们在FColor中获取到FrogColor中的date数据和调用doSomeThing 方法

上面的FrogColor中model是直接传入_FirstPageState,这样耦合度会比较高
所以我们将这个对象转为泛型,封装后如下:

新建 state_provider.dart文件:

import 'package:flutter/material.dart';

/// 使用泛型传入数据
class IProvider<T> extends InheritedWidget {
  // 数据
  final T data;
  // 方法
  final Function() doSomeThing;

  IProvider({Key key, Widget child, this.data,  this.doSomeThing})
      : super(key: key, child: child);

  @override
  bool updateShouldNotify(IProvider oldWidget) {
    return data != oldWidget.data;
  }
  static IProvider<T> of<T>(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<IProvider<T>>();
  }
}

封装好的使用需要传入数据类:

@override
Widget build(BuildContext context) {

  return Scaffold(
      appBar: AppBar(
        title: Text('InheritedWidget'),
      ),
      body: IProvider<_FirstPageState>(// 传入 _FirstPageState
        data: this
        doSomeThing: _changeColor,//提供修改数据的方法
        child: FColor('哈哈哈'),
      )
  );
}

以上就是InheritedWidget的使用,使用InheritedWidget的方式可以降低数据和UI界面的耦合。
直接使用InheritedWidget不免有些麻烦,Flutter提供了更加强大的 Provider 库,用于实现依赖注入和状态管理(后续了解之后详细介绍)。

InheritedWidget仅限与从父widget向下传递数据。那么从子widget向上传递数据如何实现呢?Notifiation就可以实现。

Notification
Notification 数据共享方式是从子 widgetw 向上传递至父widget`。

在之前的文章 Flutter 嵌套滚动 CustomScrollView 示例 中,我们使用NotificationListener去监听子child CustomScrollView的滑动距离。

同理,将子widget的数据传递给父widget也可以用这个方式实现

示例
从子widget向上发送数据,在父widget中监听到消息并打印在控制台。


以上就是Notification的使用,使用Notification的方式可以子widget的数据通过dispatch发送给父widget。
无论是 InheritedWidget还是 Notificaiton,都需要依赖与父子关系的widget。
而一些场景下的数据传递是没有这层关系的,
在Android中有事件总线的方式可以很方便的实现这类场景的数据传递,
Flutter中也有这样类似的库:EventBus

EventBus
使用Dart Streams进行应用程序解耦的简单事件总线。

示例
引入库
dependencies:
  event_bus: ^1.1.1

初始化EventBus,并定义消息数据类
final eventBus = new EventBus();

/// 传递的数据
class MsgEvent{
  final String msg;
  MsgEvent(this.msg);
}

监听
 // 监听数据变化
eventBus.on<MsgEvent>().listen((event) {
   print("接收到的数据:${event.msg}");
 });

发送数据
 eventBus.fire(MsgEvent("子 widget 发送过来的数据:老头子"));

通过以上的4步即可完成不依赖widget的数据传输。

示例完整源码
import 'package:event_bus/event_bus.dart';
import 'package:flutter/material.dart';

final eventBus = EventBus();

class FirstPage extends StatefulWidget {
  @override
  _FirstPageState createState() {
    return _FirstPageState();
  }
}

class _FirstPageState extends State<FirstPage> {

  @override
  void initState() {
    super.initState();
    // 监听数据变化
    eventBus.on<MsgEvent>().listen((event) {
      print("接收到的数据:${event.msg}");
    });
  }

  @override
  void dispose() {
    super.dispose();
    // 释放资源
    eventBus.destroy();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('EventBus'),
        ),
        body: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            // 子 widget
            RaisedButton(
              // 按钮点击时分发通知
              onPressed: () {
                eventBus.fire(MsgEvent("父 widget 发送过来的数据:我是你爸爸"));
              },
              child: Text("父 widget 发送数据"),
            ),
            CustomChild(),
          ],
        ));
  }
}

class CustomChild extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      // 按钮点击时分发通知
      onPressed: () {
        eventBus.fire(MsgEvent("子 widget 发送过来的数据:老头子"));
      },
      child: Text("子 widget 发送数据"),
    );
  }
}

/// 消息数据类
class MsgEvent{
  final String msg;
  MsgEvent(this.msg);
}

wan~


————————————————
版权声明:本文为CSDN博主「_龙衣」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ITxiaodong/article/details/105083180

 

https://www.bilibili.com/video/BV17J411J7Ko

这篇关于Flutter状态管理系列之InheritedWidget,Notifcation,eventbus的使用和原理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/508840

相关文章

从原理到实战深入理解Java 断言assert

《从原理到实战深入理解Java断言assert》本文深入解析Java断言机制,涵盖语法、工作原理、启用方式及与异常的区别,推荐用于开发阶段的条件检查与状态验证,并强调生产环境应使用参数验证工具类替代... 目录深入理解 Java 断言(assert):从原理到实战引言:为什么需要断言?一、断言基础1.1 语

使用Python实现可恢复式多线程下载器

《使用Python实现可恢复式多线程下载器》在数字时代,大文件下载已成为日常操作,本文将手把手教你用Python打造专业级下载器,实现断点续传,多线程加速,速度限制等功能,感兴趣的小伙伴可以了解下... 目录一、智能续传:从崩溃边缘抢救进度二、多线程加速:榨干网络带宽三、速度控制:做网络的好邻居四、终端交互

Python中注释使用方法举例详解

《Python中注释使用方法举例详解》在Python编程语言中注释是必不可少的一部分,它有助于提高代码的可读性和维护性,:本文主要介绍Python中注释使用方法的相关资料,需要的朋友可以参考下... 目录一、前言二、什么是注释?示例:三、单行注释语法:以 China编程# 开头,后面的内容为注释内容示例:示例:四

Go语言数据库编程GORM 的基本使用详解

《Go语言数据库编程GORM的基本使用详解》GORM是Go语言流行的ORM框架,封装database/sql,支持自动迁移、关联、事务等,提供CRUD、条件查询、钩子函数、日志等功能,简化数据库操作... 目录一、安装与初始化1. 安装 GORM 及数据库驱动2. 建立数据库连接二、定义模型结构体三、自动迁

ModelMapper基本使用和常见场景示例详解

《ModelMapper基本使用和常见场景示例详解》ModelMapper是Java对象映射库,支持自动映射、自定义规则、集合转换及高级配置(如匹配策略、转换器),可集成SpringBoot,减少样板... 目录1. 添加依赖2. 基本用法示例:简单对象映射3. 自定义映射规则4. 集合映射5. 高级配置匹

MySQL中的表连接原理分析

《MySQL中的表连接原理分析》:本文主要介绍MySQL中的表连接原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、环境3、表连接原理【1】驱动表和被驱动表【2】内连接【3】外连接【4编程】嵌套循环连接【5】join buffer4、总结1、背景

Spring 框架之Springfox使用详解

《Spring框架之Springfox使用详解》Springfox是Spring框架的API文档工具,集成Swagger规范,自动生成文档并支持多语言/版本,模块化设计便于扩展,但存在版本兼容性、性... 目录核心功能工作原理模块化设计使用示例注意事项优缺点优点缺点总结适用场景建议总结Springfox 是

嵌入式数据库SQLite 3配置使用讲解

《嵌入式数据库SQLite3配置使用讲解》本文强调嵌入式项目中SQLite3数据库的重要性,因其零配置、轻量级、跨平台及事务处理特性,可保障数据溯源与责任明确,详细讲解安装配置、基础语法及SQLit... 目录0、惨痛教训1、SQLite3环境配置(1)、下载安装SQLite库(2)、解压下载的文件(3)、

使用Python绘制3D堆叠条形图全解析

《使用Python绘制3D堆叠条形图全解析》在数据可视化的工具箱里,3D图表总能带来眼前一亮的效果,本文就来和大家聊聊如何使用Python实现绘制3D堆叠条形图,感兴趣的小伙伴可以了解下... 目录为什么选择 3D 堆叠条形图代码实现:从数据到 3D 世界的搭建核心代码逐行解析细节优化应用场景:3D 堆叠图

Springboot如何正确使用AOP问题

《Springboot如何正确使用AOP问题》:本文主要介绍Springboot如何正确使用AOP问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录​一、AOP概念二、切点表达式​execution表达式案例三、AOP通知四、springboot中使用AOP导出