详解Flutter中的数据传递
Flutter 中的数据传递
在开发中,数据从一个页面传递到另一个页面事很常用的,在Android 开发中,通常是通过把数据放到 intent 中传递过去。在 Flutter 中,数据是如何传递的呢?
在Flutter 中一切都是Widget,所以数据的传递就成了数据才Widget 中的传递。在之前的学习中,数据从一个Widget 传递到 子 Widget 是通过构造函数,一层一层的往里面传,要是 widget 的层级比较少,还没什么问题,要是层级很多,这样传递就太麻烦了。
还好Flutter 还提供了三种方案:InheritedWidget、Notification 和 EventBus来解决数据传递问题。
InheritedWidget
InheritedWidget 是 Flutter 中的一个功能型 Widget,适用于在 Widget 树中共享数据的场景。通过它,我们可以高效地将数据在 Widget 树中进行跨层传递。
下面看计数器的例子:
// 1.InheritedWidget,我们定义了一个继承自它的新类 CountContainer,里面存放需要共享的数据
//然后,我们将计数器状态 count 属性放到 CountContainer 中,并提供了一个 of 方法方便其子 Widget 在 Widget 树中找到它。
//最后,我们重写了 updateShouldNotify 方法,这个方法会在 Flutter 判断 InheritedWidget 是否需要重建,
class CountContainer extends InheritedWidget {
static CountContainer of(BuildContext context) =>
context.dependOnInheritedWidgetOfExactType<CountContainer>();
final _InheritedWidgetHomeState mode;
final Function() function;
CountContainer(
{Key key,
@required this.mode,
@required this.function,
@required Widget child})
: super(key: key, child: child);
@override
bool updateShouldNotify(covariant InheritedWidget oldWidget) {
return this != oldWidget;
}
}
// 2. 通过构建方法,把数据放到 InheritedWidget中
class _InheritedWidgetHomeState<InheritedWidgetHome> extends State {
int count = 0;
void _incrementCounter() => setState(() {
count++;
});
@override
Widget build(BuildContext context) {
return CountContainer(
mode: this,
function: _incrementCounter,
child: CountWidget(),
);
}
}
// 3. 在子 widget 通过 CountContainer.of方法,获取到自定义的 InheritedWidget,并从中取得共享的数据
class CountWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
CountContainer state = CountContainer.of(context);
return Scaffold(
appBar: AppBar(
title: Text("InheritedWidget demo"),
),
body: Text("current count is ${state.mode.count}"),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: state.function,
),
);
}
}
可以看到,InheritedWidget 的数据流动方式是从父 Widget 到子 Widget 逐层传递。
- 首先把通过构造函数需要共享的数据放到 InheritedWidget 中,然后提供一个静态方法,返回自身;
- 然后在把自定义的 InheritedWidget做为父容器,传入需要共享的数据;
- 最后在子widget 中,通过静态方法获取到 InheritedWidget 对象,自然就拿到里面的数据了。
EventBus
无论是 InheritedWidget 还是 Notificaiton,它们的使用场景都需要依靠 Widget 树,在使用起来就有点极限了,但Flutter 提供了一个更好的数据传递方法--EventBus,传递数据不再受到限制了。
在原生开发中,也有使用过 事件总线EventBus,Flutter 中实现跨组件通信的机制也是一样。它遵循发布 / 订阅模式,允许订阅者订阅事件,当发布者触发事件时,订阅者和发布者之间可以通过事件进行交互。发布者和订阅者之间无需有父子关系,甚至非 Widget 对象也可以发布 / 订阅。这些特点与其他平台的事件总线机制是类似的。
由于 EventBus是第三方库,所以需要引入:
event_bus: 2.0.0
从第二个页面,把数据回传到第一个页面
//建立公共的event bus
EventBus eventBus = EventBus();
class CustomEvent {
String msg;
CustomEvent(this.msg);
}
class _EventBusPager1State extends State {
String message = "原来的数据";
StreamSubscription subscription;
@override
void initState() {
subscription = eventBus.on<CustomEvent>().listen((event) {
setState(() {
message = event.msg;
});
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("EventBusPager1"),
),
body: Center(
child: Text(message),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.open_in_browser),
onPressed: () => Navigator.push(
context, MaterialPageRoute(builder: (context) => EventBusPager2())),
),
);
}
@override
void dispose() {
subscription.cancel();
super.dispose();
}
}
class EventBusPager2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("EventBusPager2"),
),
body: Center(
child: Text("EventBusPager1"),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.send),
onPressed: () {
eventBus.fire(CustomEvent("data from page 2"));
Navigator.pop(context);
},
),
);
}
}
总结
通过学习了解了 在Flutter 中如何传递数据的,大致分为四种方式:
- 通过属性,一层一层往下传
- 通过 把数据写到 InheritedWidget的子类,然后把共享的数据放到里面,并提获取自身的供静态方法,在需要的地方通过静态方法获取到 InheritedWidget对象,并获取数据,这种方式是能从父widget 传递到子widget;
- 通过 Notifaction 发送消息,然后再父 widget 进行监听;
- 通过eventBus ,通过发布 / 订阅模式,来完成数据的传递,也是开发中常用的。
以上就是详解Flutter中的数据传递的详细内容,更多关于Flutter中的数据传递的资料请关注编程网其它相关文章!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341