Flutter中跨组件数据传递的方法总结

Angie ·
更新时间:2024-05-16
· 906 次阅读

目录

方法1:InheritedWidget

方法2:Notification

方法3:EventBus

方法1:InheritedWidget

InheritedWidget:它提供了一种数据在Widget树中从上向下传递,共享的方式。我们在应用的根Widget中通过InheritedWidget共享了一个数据,那么我们可以在任意子Widget中获取该共享的数据!其通用方式就是:

class ShareDataWidget extends InheritedWidget { final int data; ShareDataWidget({this.data, Widget child}) : super(child: child); static ShareDataWidget of(BuildContext context){ return context.dependOnInheritedWidgetOfExactType<ShareDataWidget>(); } @override bool updateShouldNotify(ShareDataWidget oldWidget) { return oldWidget.data !=data; } }

其实就是继承InheritedWidget,首先定义需要保存的数据比如这里的int型data,然后实现updateShouldNotify方法,最后定义一个获取该Widget的静态方法,在需要使用该保存数据的时候通过这个静态方法获取。使用时,在父widget中传入需要保存的data,在child中通过定义的静态方法来获取最新值。比如定义的parent如下

class Parent extends StatefulWidget { Parent({Key key}) : super(key: key); _ParentState createState() => _ParentState(); } class _ParentState extends State<Parent> with WidgetsBindingObserver { int _counter = 0; //当Widget第一次插入到Widget树时会被调用。对于每一个State对象,Flutter只会调用该回调一次 @override void initState() { super.initState(); print("page2 parent initState......"); } @override void setState(fn) { super.setState(fn); print("page2 parent setState......"); } /* *初始化时,在initState之后立刻调用 *当State的依赖关系发生变化时,会触发此接口被调用 */ @override void didChangeDependencies() { super.didChangeDependencies(); print("page2 parent didChangeDependencies......"); } @override void didChangeAppLifecycleState(AppLifecycleState state) { print("page2 state is $state"); } //绘制界面 @override Widget build(BuildContext context) { print("page2 parent build......"); return Scaffold( appBar: AppBar(title: Text("setState demo")), body: Center( child: ShareDataWidget( data: _counter, child: RaisedButton( ///点击事件 onPressed: () { setState(() { _counter++; }); }, child: Child(), ), )), ); } //状态改变的时候会调用该方法,比如父类调用了setState @override void didUpdateWidget(Parent oldWidget) { super.didUpdateWidget(oldWidget); print("page2 parent didUpdateWidget......"); } //当State对象从树中被移除时,会调用此回调 @override void deactivate() { super.deactivate(); print('page2 parent deactivate......'); } //当State对象从树中被永久移除时调用;通常在此回调中释放资源 @override void dispose() { super.dispose(); print('page2 parent dispose......'); } }

可以看到我们传入了_counter属性到ShareDataWidget中,并且SharedDataWidget的child需要使用共享的变量。我们的Child定义如下

class Child extends StatefulWidget { Child({Key key}) : super(key: key); @override _ChildState createState() => _ChildState(); } class _ChildState extends State<Child> { //绘制界面 @override Widget build(BuildContext context) { print("child build......"); return Text.rich(TextSpan(children: [ TextSpan( text: '点击按钮查看状态变化 count: ${ShareDataWidget.of(context).data.toString()}', style: TextStyle(color: Color.fromARGB(100, 255, 0, 0))), TextSpan( text: "新加的一段文本", style: TextStyle(color: Colors.blue), recognizer: TapGestureRecognizer() ..onTap = () { print("点击了文本"); }) ])); } //当Widget第一次插入到Widget树时会被调用。对于每一个State对象,Flutter只会调用该回调一次 @override void initState() { super.initState(); print("page2 child initState......"); } /* *初始化时,在initState之后立刻调用 *当State的依赖关系发生变化时,会触发此接口被调用 */ @override void didChangeDependencies() { super.didChangeDependencies(); print("page2 child didChangeDependencies......"); } //状态改变的时候会调用该方法,比如父类调用了setState @override void didUpdateWidget(Child oldWidget) { super.didUpdateWidget(oldWidget); print("page2 child didUpdateWidget......"); } //当State对象从树中被移除时,会调用此回调 @override void deactivate() { super.deactivate(); print('page2 child deactivate......'); } //当State对象从树中被永久移除时调用;通常在此回调中释放资源 @override void dispose() { super.dispose(); print('page2 child dispose......'); } }

其使用就是在Parent中用创建好的ShareDataWidget作为父Widget,在父widget更新需要保存的变量时,同时将数据保存在ShareDataWidget的data中,比如上面在parent的build方法中

真正使用这个值的地方是Child类,它的build方法

在parent中触发onPress事件其调用如下

通过使用方式可以看到明显适用于父->子

方法2:Notification

Notification它的数据传递方式是从子Widget向上传递给父Widget。比如先定义一个notification,这里只有一个msg需要传递给父Widget。

class CustomNotification extends Notification{ final String msg; CustomNotification(this.msg); }

然后定义一个子Widget来发送这个通知

class CustomChild extends StatelessWidget{ @override Widget build(BuildContext context) { return ElevatedButton(onPressed: ()=>CustomNotification("HI").dispatch(context),child: Text("FireNotification"),); } }

在父widget中使用这个通知

class ParentPage extends StatefulWidget { @override State<StatefulWidget> createState() { return _ParentPageState(); } } class _ParentPageState extends State<ParentPage> { String msg = "通知"; @override Widget build(BuildContext context) { return NotificationListener<CustomNotification>( onNotification: (notification){ setState(() { msg+=notification.msg+" "; }); }, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [Text(msg), CustomChild()], )); } }

可以看到父widget中的根是NotificationListener这个监听器,刚才定义的CustomChild是他的子Widget。

方法3:EventBus

这种方式在Android中也经常使用,这个就比较简单了。首先引用该组件event_bus: ^2.0.0。可以在全局声明一个EventBus实例,比如在main.dart中。

EventBus bus = new EventBus();

在需要接收订阅的类中

StreamSubscription subscription; String msg = "event Msg"; //当Widget第一次插入到Widget树时会被调用。对于每一个State对象,Flutter只会调用该回调一次 @override void initState() { subscription = bus.on<CustomEvent>().listen((event) { setState(() { msg+=event.msg+" "; }); }); super.initState(); print("page1 initState......"); }

这里的subscription其实就是为了防止泄露的,在dispose的时候我们要解除订阅,CustomEvent其实就是一个类,

class CustomEvent{ String msg; CustomEvent(this.msg); }

在需要发送通知的地方

bus.fire(CustomEvent("我是EventBus发送的"));

这个比较适合于父->父。也就是所谓的“页面间”的数据传递

以上就是Flutter中跨组件数据传递的方法总结的详细内容,更多关于Flutter数据传递的资料请关注软件开发网其它相关文章!



方法 数据 flutter

需要 登录 后方可回复, 如果你还没有账号请 注册新账号
相关文章