目录
在Flutter中,常见的数据传递一共有以下几种:
1、构造方法传递
Flutter
的构造方法具备着dart
语言的特点,参数具备可选状态,通过构造方法传递数据,可以很方便的将任意数据进行传递,平时开发中,A
跳转B
页面最常用的方法就是通过构造方法进行传递。比如我们最常见的Key
就是通过构造一级一级向下传递的。
优点: 相邻页面之间传递数据非常方便,你不需要进行任何额外的操作。
缺点: 当页面层级过多以及类过多时,需一级一级传递,写起来非常麻烦,代码耦合性高。
2、InheritedWidget
为了解决构造函数一级一级乡下传递的的缺点,Flutter派生出了功能性组件InheritedWidget
,通过它可以实现顶级widget的数据共享,也就是说无需一级一级向下传递,即可获取数据,比如A页面有一个数据,需要在C页面使用,那么就可以不经过B页面获取,前提ABC三个页面是属于一个Widget中的,常见的 TabView布局顶层数据共享,适合复杂页面顶层向下传递数据,使用也很简单。
示例代码:
/// 数据共享 class TestData extends InheritedWidget { final Widget child; final String data; // 共享数据 // 构造 const TestData({ Key? key, required this.child, required this.data, }) : super(key: key, child: child); /// 定义一个静态方法 获取数据 static String of(BuildContext context) { // return context.dependOnInheritedWidgetOfExactType<TestDataestData>()?.data??"数据有误"; return (context.getElementForInheritedWidgetOfExactType<TestData>()?.widget as TestData).data ; } @override bool updateShouldNotify(covariant TestData oldWidget) { return child != oldWidget.child; } }
然后在A页面的根布局套上TestData
,在C页面通过of
方法即可获取数据。
两种更新数据方法:
dependOnInheritedWidgetOfExactType
: 子组件更新didChangeDependencies();
getElementForInheritedWidgetOfExactType
: 不更新。
需要注意的点: 这种传递方式是树状结构从上而下进行传递,所共享数据的页面必须在顶层的build
方法中,并且没有延迟加载,比如这个页面为动态加载,那么在C页面中的initState
获取数据就会报错,原因就是首次构建时,没有加载子页面导致,可在build方法中获取,或者延时获取。
优点: 自上而下,无需一级一级传递,传递方便。
缺点: 不能跨组件传递。
应用场景: 系统中比如我们常见的MediaQuery
设备信息和Theme
应用主题就是通过这种方式在来进行统一数据共享的。
3、Notification
Notification
是FLutter中的一种通知机制,和 InheritedWidget
相反,他可以自下而上通知父组件更新数据,
定义传递数据类:
class TestDataN extends Notification{ final String data; TestDataN(this.data); }
子组件通知调用dispacth方法通知父组件。
TestDataN("data").dispatch(context);
在父组件进行监听:
NotificationListener( onNotification: (data){ print("data$data"); return true; },child: child);
应用场景: 比如我们的ListView
滚动监听、就是通过Notification
实现的。
4、Stream & event_bus
以上的2、3数据传递方式都是基于同一个widget树进行传递的,跨组件通信我们可以使用Stream事件流进行传递,通过订阅者模式监听数据,可以在任意组件中进行数据传递,event_bus插件就是使用这种方式来进行数据传递的。
eventBus示例代码:
// 创建公用对象 EventBus eventBus = EventBus(); // 监听数据 eventBus.on().listen((event) { }); // 发送 eventBus.fire(event);
使用完毕在注册接收数据页面记得销毁:eventBus.destroy();
优点: 可以跨组件通信。