常见的数据共享有以下几种
image.png
一、InheritedWidget (父到子)
CountContainer(
//increment: _incrementCounter,
model: this,
increment: _incrementCounter,
child:Counter()
);
1)、父widget提供了一个 of 方法方便其子 Widget 在 Widget 树中找到它。
class CountContainer extends InheritedWidget {
static CountContainer of(BuildContext context) => context.dependOnInheritedWidgetOfExactType<CountContainer>() as CountContainer;
final _CounterPageState model;
final Function() increment;
CountContainer({
Key? key,
required this.model,
required this.increment,
required Widget child,
}): super(key: key, child: child);
@override
bool updateShouldNotify(CountContainer oldWidget) => model != oldWidget.model;
}
2)、在子 Widget Counter 中,我们通过 InheritedCountContainer.of 方法找到它
class Counter extends StatelessWidget {
@override
Widget build(BuildContext context) {
CountContainer state = CountContainer.of(context);
return Scaffold(
appBar: AppBar(
title: Text("InheritedWidget demo"),
),
body: Text(
'You have pushed the button this many times: ${state.model.count}',
),
floatingActionButton: FloatingActionButton(onPressed: state.increment),
);
}
二、Notification (子到父)
定义通知:
class CustomNotification extends Notification {
CustomNotification(this.msg);
final String msg;
}
子widget发送通知
class CustomChild extends StatelessWidget {
@override
Widget build(BuildContext context) {
return RaisedButton(
//按钮点击时分发通知
onPressed: () => CustomNotification("Hi").dispatch(context),
child: Text("Fire Notification"),
);
}
}
父widget监听
class _NotificationState extends State<NotificationWidget> {
String _msg = "通知:";
@override
Widget build(BuildContext context) {
//监听通知
return NotificationListener<CustomNotification>(
onNotification: (notification) {
setState(() {_msg += notification.msg+" ";});
return true;
},
child:Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[Text(_msg),CustomChild()],
)
);
}
}
三、EventBus (跨组件)遵循发布 / 订阅模式
类似于原生的通知
1、引用:
dev_dependencies:
flutter_test:
sdk: flutter
event_bus: ^2.0.0 # 确保版本支持空安全
2、使用:
定义事件
class CustomEvent {
String msg;
CustomEvent(this.msg);
}
然后定义了一个全局的 eventBus 对象,并在第一个页面监听了 CustomEvent 事件,一旦收到事件,就会刷新 UI。需要注意的是,千万别忘了在 State 被销毁时清理掉事件注册,否则你会发现 State 永远被 EventBus 持有着,无法释放,从而造成内存泄漏
EventBus eventBus = new EventBus();
class FirstPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => _FirstPageState();
}
class _FirstPageState extends State<FirstPage> {
String msg = "通知:";
late StreamSubscription subscription;
@override
void initState() {
//监听CustomEvent事件,刷新UI
subscription = eventBus.on<CustomEvent>().listen((event) {
print(event);
setState(() {
msg += event.msg;
});
});
super.initState();
}
dispose() {
subscription.cancel(); //State销毁时,清理注册
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("First Page"),
),
body: Text(msg),
floatingActionButton: FloatingActionButton(
onPressed: () => Navigator.push(
context, MaterialPageRoute(builder: (context) => SecondPage()))),
);
}
}
第二个页面进行发送通知
class SecondPage extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Page"),
),
body: RaisedButton(
child: Text('Fire Event'),
// 触发CustomEvent事件
onPressed: () => eventBus.fire(CustomEvent("hello"))),
);
}
}