Flutter组件数据共享/传递

常见的数据共享有以下几种

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"))),
    );
  }
}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容