js css html大前端开发flutter

Flutter|常用数据通信组件

2022-06-05  本文已影响0人  厘米姑娘

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

父子组件之间的通信

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

Provider

// 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

NotificationListener

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

兄弟组件之间的通信

ValueListenableBuilder

// 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();
  ...
}

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中常用的组件,整体看ProviderEventBus总是能很好的处理各类场景,功能强大,但也有维护成本的问题(比如要新增很多事件类等),一些简单场景可以考虑其他小组件。

上一篇 下一篇

猜你喜欢

热点阅读