Flutter|常用数据通信组件

简介: 在做需求时经常会遇到组件间通信,本篇汇总了几种常用的通信方式

父子组件之间的通信
最简单的方式就是通过构造器传递数据,但当嵌套层级比较深的时,传参就比较难看了,或许这时还考虑用单例,但对于简单数据来说未免大材小用了。
例如,还是这个二级页场景,由多个子孙组件组成(同色框表示同级),在顶层页面可以知道从上个页面携带的数据,但最下层的输入框组件(箭头位置)也需要知道部分数据才能发送评论,这里说下如何用Provider快速实现。

Provider
介绍:基于InheritedWidget,一种自上向下的共享数据机制,方便子孙节点得到祖先节点共享的数据。
举例:

// 1、添加依赖
dependencies:
  provider: ^5.0.0

// 2、通过Provider包裹的child都共享数据 feedShareData
...
return Scaffold(
  ...
  body: Provider(
    create: (_) => feedShareData,
    child: Builder(builder: (context) {
   
      return FeedDetailPage();
    }),
  ),
);
// 3、在子孙组件都可以读取并修改共享数据
feedShareData = context.read<NormalFeedsDetailShareData>();
...

适用场景:当子组件需要共享祖先/父组件的数据时,尤其在跨层传递场景。
除了数据共享外,还有就是数据传递,也就是组件想知道另个组件的某些变化,并做出反应(callback)。在Dart中函数是可以当做对象传递的,但同样存在层级复杂时可能要传递大量的函数,接下来介绍常用的数据传递组件。

ChangeNotifier
介绍:可用于扩展Model,并在Model发生变化时调用notifyListeners使得监听该Model的组件重新构建。
举例:详见官方提供的案例,实现了加入购物车的效果。
适用场景: 常和Provider(Consumer)配套解决数据共享&状态传递问题。
NotificationListener
介绍:通知机制,即每个节点都可以向上发送Notification(自下向上的),除非中途被拦截否则会一直向上传。
举例:在上篇Flutter小白|初探事件处理介绍了如何通过NotificationListener解决多个滑动组件下、监听最外层组件滑动到边界事件,可见使用NotificationListener可以很方便获取到可滑动子组件的滑动行为。当然还可以在子组件上通过Notification#dispatch发送自定义通知,然后在上层接收并处理。

// 1、自定义通知类
class CustomNotification extends Notification {
   
  String msg;
  CustomNotification(this.msg);
}
// 2、子组件发送通知
...
CustomNotification("Test").dispatch(context);
...
// 3、父组件接收和处理通知
...
NotificationListener<CustomNotification>(
      onNotification: (notification) {
   
       // 处理逻辑
         // 同样的返回值表示是否拦截
       return true;
      },
      child:...
)

适用场景:当祖先/父组件要随着子组件的某些情况变化而变化时,常用于滑动情况。
兄弟组件之间的通信
ValueListenableBuilder
介绍:顾名思义,对某个 value进行监听,只要value发生变化就会直接通过setState重新构建子组件树。同样的,因为会rebuild,使用时尽可能缩小包裹的组件范围,以减少不必要的组件被重建、提高性能。
举例:例如想要实现这样的需求,底部输入框有内容时按钮亮起,无内容按钮置灰,代码如下:

// 1、创建:定义一个文本内容的ValueNotifier,
ValueNotifier<String> emojiInfoNotifier = ValueNotifier("");

// 2、使用:输入框组件和按钮组件都监听这个string信息
...
ValueListenableBuilder(
  valueListenable: emojiInfoNotifier,
  builder: (BuildContext context, String value, Widget? child) {
   
    // 输入框组件,根据输入内容展示,没有内容展示默认文案
    return Text(
      value.isEmpty
          ? Strings.share_thoughts
          : value,
      maxLines: 1,
      overflow: TextOverflow.ellipsis,
      style: TextStyle(fontSize: Res.t12, color: Res.c1),
    );
  },
),
...
ValueListenableBuilder(
  valueListenable: emojiInfoNotifier,
  builder: (BuildContext context, String value, Widget? child) {
   
    // 按钮组件,根据有无内容改变icon颜色
    return SvgPicture.asset(
      iconUrl,
      color: value.isEmpty ? Res.c4 : Res.c2,
      width: 16,
      height: 16,
    );
  },
),
...
// 3、随数据变化而变化:当点击表情按钮导致文本内容发生变化时,输入框组件和按钮组件都会发生变化,
...
GestureDetector(
  behavior: HitTestBehavior.opaque,
  onTap: () {
   
    // 超过最大表情展示个数会弹toast提示
    if (emojiInfoNotifier.value.characters.length >= maxInputEmojiCount) {
   
      Toasts.show(Strings.input_more);
    } else {
   
      emojiInfoNotifier.value += emoji?.text ?? "";
    }
  },
  child:... // 表情按钮
)...
// 4、销毁:在依赖组件dispose的同时销毁
@override
void dispose() {
   
  super.dispose();
  emojiInfoNotifier.dispose();
  ...
}

适用场景:当组件A要随着其他组件B上操作的数据变化而变化时,可以在同个组件树,也可以不是。常用于组件关系不复杂且监听数据简单的情况。
EventBus
介绍:对于要跨组件甚至跨页面组件通信的,这时用EventBus屡试不爽。关于 EventBus 开发一定非常熟悉了,核心就是观察者模式,一方发布消息,一方订阅感兴趣的消息并做处理。
举例:
// 1、添加依赖
dependencies:
event_bus: ^2.0.0

// 2、新增事件类
class CustomEvent {
String msg;
CustomEvent(this.msg);
}

// 3、发送事件(用单例维护,这里不展示了)
EventBusExt.getDefault().fire(CustomEvent("test"));

// 4、订阅事件并处理

EventBusExt.getDefault().on<CustomEvent>().listen((event) {
   
      // 处理逻辑
});

适用场景:可以在任何位置传递事件,可以解决大多数通信需求。
总结
本篇从数据通信方式(共享数据、传递数据)和组件关系(父子关系、兄弟关系)两方面分别介绍了Flutter中常用的组件,整体看Provider和EventBus总是能很好的处理各类场景,功能强大,但也有维护成本的问题(比如要新增很多事件类等),一些简单场景可以考虑其他小组件。

相关文章
|
4月前
Flutter 组件(二)文本 与 输入框组件
Flutter 组件(二)文本 与 输入框组件
301 0
|
4月前
|
容器
Flutter 组件(一)组件概述
Flutter 组件(一)组件概述
91 0
|
13天前
|
容器
Flutter基本组件Text使用
Flutter基本组件Text使用
37 12
|
8天前
|
开发工具
Flutter-AnimatedWidget组件源码解析
Flutter-AnimatedWidget组件源码解析
|
2月前
|
Dart 开发者 UED
flutter 非常用组件整理 第三篇
本文是非常用组件的第三讲,介绍了一些不为人知但却能大幅提升Flutter应用UI效果和功能的高级组件,包括FadeInImage、GridPaper、Hero等,为开发者带来更丰富的UI设计可能。
flutter 非常用组件整理 第三篇
|
2月前
|
Dart 数据安全/隐私保护 开发者
flutter 非常用组件整理 第二篇
本文是Flutter非常用组件第二篇,从开发者的视角出发,精选并深入剖析了AboutDialog、AnimatedGrid、Badge等鲜为人知却功能强大的隐藏组件,为读者提供了一份全面的Flutter UI组件使用指南。无论您是初学者还是有经验的开发者,相信本文都能为您的Flutter项目注入新的活力,助力打造出色的应用界面。
flutter 非常用组件整理 第二篇
|
1月前
|
开发工具
解决Flutter中ThemeData.primaryColor在AppBar等组件中不生效
解决Flutter中ThemeData.primaryColor在AppBar等组件中不生效
28 1
|
1月前
|
开发者 容器
Flutter笔记:Widgets Easier组件库(3)使用按钮组件
Flutter笔记:Widgets Easier组件库(3)使用按钮组件
25 2
|
2月前
flutter 导航组件 AppBar (含顶部选项卡TabBar,抽屉菜单 drawer ,自定义导航图标)
flutter 导航组件 AppBar (含顶部选项卡TabBar,抽屉菜单 drawer ,自定义导航图标)
33 1
|
4月前
|
Dart
Flutter 中优雅切换应用主题的组件
【Flutter】使用adaptive_theme组件优雅切换应用主题:封装MaterialApp,支持light/dark/system模式,自定义色彩,保存选择,含调试按钮。安装配置、设置主题、监听切换、自定义颜色、读取配置步骤详细。代码示例与学习路径推荐。[查看完整教程](https://flutter.ducafecat.com/blog/flutter-app-theme-switch)
Flutter 中优雅切换应用主题的组件