扣丁书屋

Flutter 入门笔记(Part 6) 跨组件共享数据,路由管理

14 . 跨组件共享数据

视图层级比较深的UI样式,直接通过属性传值会导致很多中间层增加冗余属性.

  • 代码太多,见demo https://github.com/xfhy/FlutterBasic/tree/master/lib/data

14.1 InheritedWidget

  • 共享父Widget的属性

14.2 Notification

  • 从下往上的数据传递,在父Widget中监听来自子Widget的事件

14.3 EventBus

  • EventBus 不依赖Widget树 这是事件总线,666
  • 遵循发布订阅 模式

14.4 对比

方式 数据流动方式 使用场景
属性传值 父到子 简单数据传递
InheritedWidget 父到子 跨层数据传递
Notification 子到父 状态通
EventBus 发布订阅 消息批量同步

15 . 路由管理

  • Route是页面的抽象,主要负责创建对应的界面,接收参数,响应Navigator打开和关闭
  • Navigator则会维护一个路由栈管理Route,Route打开即入栈,Route关闭即出栈.
  • 基本路由: 创建一个MaterialPageRoute实例,调用Navigator.push方法将新页面压到堆栈的顶部
class FirstScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      //打开页面
      onPressed: ()=> Navigator.push(context, MaterialPageRoute(builder: (context) => SecondScreen()));
    );
  }
}

class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      // 回退页面
      onPressed: ()=> Navigator.pop(context)
    );
  }
}
  • 命名路由: 简化路由管理,命名路由.给页面起一个名字,然后通过名字打开
MaterialApp(
    ...
    //注册路由
    routes:{
      "second_page":(context)=>SecondPage(),
    },
);
//使用名字打开页面
Navigator.pushNamed(context,"second_page");
  • 错误路由处理,统一返回UnknownPage

MaterialApp(
    ...
    //注册路由
    routes:{
      "second_page":(context)=>SecondPage(),
    },
    //错误路由处理,统一返回UnknownPage
    onUnknownRoute: (RouteSettings setting) => MaterialPageRoute(builder: (context) => UnknownPage()),
);

//使用错误名字打开页面
Navigator.pushNamed(context,"unknown_page");
  • 页面参数: Flutter提供了路由参数的机制,可以在打开路由时传递相关参数,在目标页面通过RouteSettings来获取页面参数
//打开页面时传递字符串参数
Navigator.of(context).pushNamed("second_page", arguments: "Hey");

class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //取出路由参数
    String msg = ModalRoute.of(context).settings.arguments as String;
    return Text(msg);
  }
}
  • 返回参数(类似startActivityForResult): 在push目标页面时,可以设置目标页面关闭时监听函数,以获取返回参数.而目标页面可以在关闭路由时传递相关参数.
class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: <Widget>[
          Text('Message from first screen: $msg'),
          RaisedButton(
            child: Text('back'),
            //页面关闭时传递参数
            onPressed: ()=> Navigator.pop(context,"Hi")
          )
        ]
      ));
  }
}

class _FirstPageState extends State<FirstPage> {
  String _msg='';
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: Column(children: <Widget>[
        RaisedButton(
            child: Text('命名路由(参数&回调)'),
            //打开页面,并监听页面关闭时传递的参数
            onPressed: ()=> Navigator.pushNamed(context, "third_page",arguments: "Hey").then((msg)=>setState(()=>_msg=msg)),
        ),
        Text('Message from Second screen: $_msg'),

      ],),
    );
  }
}
  • Navigator.push A->B->C->D,如何从 D页面 pop 到 B 呢? Navigator.popUntil(context,ModalRoute.withName('B'));

https://mp.weixin.qq.com/s/n9xpBiDSiqE7JCPnbrsO6Q

最多阅读

如何有效定位Flutter内存问题? 9月以前  |  10184次阅读
Flutter的手势GestureDetector分析详解 2年以前  |  5108次阅读
Flutter插件详解及其发布插件 2年以前  |  4192次阅读
在Flutter中添加资源和图片 2年以前  |  3807次阅读
发布Flutter开发的iOS程序 2年以前  |  3033次阅读
Flutter 状态管理指南之 Provider 2年以前  |  2781次阅读
在Flutter中发起HTTP网络请求 2年以前  |  2685次阅读
Flutter for Web详细介绍 2年以前  |  2639次阅读
使用Inspector检查用户界面 2年以前  |  2605次阅读
Flutter Widget框架概述 2年以前  |  2357次阅读
Flutter框架概览 2年以前  |  2200次阅读
JSON和序列化 2年以前  |  2197次阅读
为Flutter应用程序添加交互 2年以前  |  2175次阅读
Flutter路由详解 2年以前  |  2168次阅读
处理文本输入 2年以前  |  2042次阅读
使用自定义字体 2年以前  |  2033次阅读
编写国际化Flutter App 2年以前  |  1992次阅读
推荐5个Flutter重磅开源项目! 1年以前  |  1987次阅读

手机扫码阅读