详解Flutter中的数据传递

目录
  • Flutter 中的数据传递
    • InheritedWidget
    • EventBus
    • 总结

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 逐层传递。

  1. 首先把通过构造函数需要共享的数据放到 InheritedWidget 中,然后提供一个静态方法,返回自身;
  2. 然后在把自定义的 InheritedWidget做为父容器,传入需要共享的数据;
  3. 最后在子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 中如何传递数据的,大致分为四种方式:

  1. 通过属性,一层一层往下传
  2. 通过 把数据写到 InheritedWidget的子类,然后把共享的数据放到里面,并提获取自身的供静态方法,在需要的地方通过静态方法获取到 InheritedWidget对象,并获取数据,这种方式是能从父widget 传递到子widget;
  3. 通过 Notifaction 发送消息,然后再父 widget 进行监听;
  4. 通过eventBus ,通过发布 / 订阅模式,来完成数据的传递,也是开发中常用的。

以上就是详解Flutter中的数据传递的详细内容,更多关于Flutter中的数据传递的资料请关注我们其它相关文章!

(0)

相关推荐

  • Flutter 和 Android 互相传递数据的实现

    (一)Android代码设置 1,打开Android Studio 创建一个应用程序,包名dev.android.book 2, 创建一个MyApplication ,应用在AndroidManifest.xml文件中的application的android:name属性上 3,创建FlutterEngine的实例,然后把这个实例添加到缓存的FlutterEngine当中 4,创建MethodChannel的实例,指定一个此实例的唯一字符串,例如dev.android.book/add 5, 设

  • Flutter持久化存储之数据库存储(sqflite)详解

    前言 数据库存储是我们常用的存储方式之一,对大批量数据有增.删.改.查操作需求时,我们就会想到使用数据库,Flutter中提供了一个sqflite插件供我们用于大量数据执行CRUD操作.本篇我们就来一起学习sqflite的使用. sqflite是一款轻量级的关系型数据库,类似SQLite. 在Flutter平台我们使用sqflite库来同时支持Android 和iOS. sqflite使用 引入插件 在pubspec.yaml文件中添加path_provider插件,最新版本为1.0.0,如下:

  • Flutter上的数据监控深入理解

    前言 最近看公司Flutter项目的时候,发现想要分析数据非常的困难,不是数据缺失就是数据异常,作为一个成熟的企业来说这是非常危险的,缺少了数据就像船只在海上航行的时候没有了方向,将会变得无所适从,所以这周花了点时间去优化. 我们要关注什么数据 对于Flutter这样的组件来说,我们需要关注的数据无非是两项: 性能数据 异常数据 这两项数据是我们监控整个Flutter应用是否优秀的最基础也是最重要的指标.性能数据能够帮我们分析出Flutter对比Native,RN,Weex等框架是否有优势,而异

  • Flutter List数组避免插入重复数据的实现

    List 具有一定长度存在索引的对象集合(长度为0不存在索引,长度>0存在索引) 常见列表 1.定长列表 默认值null 例如:List<int> fixedLengthList = new List(2).List<int> fixedLengthList = new List(8) List<int> fixedLengthList = new List(2); for(int i=0;i<2;i++){ print("索引为${i}的值${f

  • Flutter学习教程之Route跳转以及数据传递

    前言 我们知道移动应用页面跳转是非常重要的一部分,几乎我们的程序和用户打交道的就是页面,或者叫view,我们Android基本都是Activity和Fragment.而且Flutter当中叫做Route,它就是与用户打交道的页面.本文详细探索一下Flutter当中页面之间是怎么交互的. Route类似Android中Activity,所以Flutter中的页面跳转类似Android中Activity之间跳转,Intent携带传递的数据. 正文 页面跳转 我们现在看看Flutter中是怎么进行页面

  • 详解Flutter中的数据传递

    目录 Flutter 中的数据传递 InheritedWidget EventBus 总结 Flutter 中的数据传递 在开发中,数据从一个页面传递到另一个页面事很常用的,在Android 开发中,通常是通过把数据放到 intent 中传递过去.在 Flutter 中,数据是如何传递的呢? 在Flutter 中一切都是Widget,所以数据的传递就成了数据才Widget 中的传递.在之前的学习中,数据从一个Widget 传递到 子 Widget 是通过构造函数,一层一层的往里面传,要是 wid

  • 详解Flutter中数据传递的方式

    目录 1.构造方法传递 2.InheritedWidget 3.Notification 4.Stream & event_bus 在Flutter中,常见的数据传递一共有以下几种: 1.构造方法传递 Flutter的构造方法具备着dart语言的特点,参数具备可选状态,通过构造方法传递数据,可以很方便的将任意数据进行传递,平时开发中,A跳转B页面最常用的方法就是通过构造方法进行传递.比如我们最常见的Key就是通过构造一级一级向下传递的. 优点: 相邻页面之间传递数据非常方便,你不需要进行任何额外

  • 详解Django中views数据查询使用locals()函数进行优化

    优化场景 利用视图函数(views)查询数据之后可以通过上下文context.字典.列表等方式将数据传递给HTML模板,由template引擎接收数据并完成解析.但是通过context传递数据可能就存在在不同的视图函数中使用重复的查询语句,所以可以通过将重复查询语句设置全局变量,配合locals()函数进行数据查询与传递. 优化前 def index(request): threatname = '威胁情报展示' url = 'www.testtip.com' allthreat = Threa

  • 详解MySQL中的数据类型和schema优化

    最近在学习MySQL优化方面的知识.本文就数据类型和schema方面的优化进行介绍. 1. 选择优化的数据类型 MySQL支持的数据类型有很多,而如何选择出正确的数据类型,对于性能是至关重要的.以下几个原则能够帮助确定数据类型: 更小的通常更好 应尽可能使用可以正确存储数据的最小数据类型,够用就好.这样将占用更少的磁盘.内存和缓存,而在处理时也会耗时更少. 简单就好 当两种数据类型都能胜任一个字段的存储工作时,选择简单的那一方,往往是最好的选择.例如整型和字符串,由于整型的操作代价要小于字符,所

  • 详解Flutter中视频播放器插件的使用教程

    目录 创建一个新的视频播放器 添加播放和暂停按钮 创建一个快进 添加一个视频进度指示器 应用视频的字幕 结论 您已经看到很多包含视频内容的应用程序,比如带有视频教程的食谱应用程序.电影应用程序和体育相关的应用程序.您是否想知道如何将视频内容添加到您的下一个Flutter应用程序中? 从头开始实现视频功能将是一项繁重的任务.但有几个插件可以让开发者的生活变得轻松.视频播放器插件是可用于 Flutter 的最佳插件之一,可满足这一要求. 在这篇文章中,您将学习如何应用视频播放器插件以及控制视频播放器

  • 详解Flutter中网络框架dio的二次封装

    其实dio框架已经封装的很好了,但是在实战项目中,为了项目可以统一管理,还是需要对dio框架进行二次封装. 整体思路:一般情况下,后台返回的数据我们可以分为两部分 1.状态数据 2.渲染数据 状态数据就是接口有没有正常返回数据相关的数据,这部分数据跟业务无关,我们可以封装起来统一管理,渲染数据就是我们渲染页面所需要的数据,这块的数据需要我们自己处理. 接下来我们就主要处理渲染数据这块的内容,我定义了两个函数,渲染数据可能为一个对象或者一个数组,我做了分别处理,定义两个函数来接受渲染数据. //

  • 详解Flutter中Dart集合使用教程

    目录 前言 优先使用集合的特有语法 不要使用.length 属性判断集合是不是为空 避免使用 forEach 迭代元素 不要使用 List.from(),除非你想要更改结果的类型 使用 whereType 过滤类型 避免使用 cast() 做强制转换 总结 前言 集合是应用程序中最为常见的数据结构,Dart 一共支持如下四种集合,其中核心的 List, Map 和 Set 在基础框架中,而 Queue 在 dart:collection 库定义. 列表:也就是 List类,可动态增长的数组: k

  • 微信小程序 详解Page中data数据操作和函数调用

    微信小程序 详解Page中data数据操作和函数调用 Page() 函数用来注册一个页面.接受一个 object 参数,其指定页面的初始数据.生命周期函数.事件处理函数等. //index.js <pre code_snippet_id="2049407" snippet_file_name="blog_20161214_1_1145312" name="code" class="javascript">Page(

  • 详解Java中JSON数据的生成与解析

    一.什么是JSON JSON: JavaScript Object Notation JS对象简谱,是一种类似于XML的语言.相比于XML,它更小.更快.更易解析.主要用于项目前端和Server的网络数据传输. 二.JSON的语法 对象 一个对象,由一个大括号表示{},{}中通过一个个的键值对来描述对象的属性 注意: 键与值之间使用冒号连接,多个键值对之间使用逗号分隔. 键值对的键,应使用引号引住(通常Java解析时,键不使用引号会报错,而JS能正确解析):键值对的值,可以是JS中的任意数据类型

  • 详解flutter中常用的container layout实例

    目录 简介 Container的使用 旋转Container Container中的BoxConstraints 总结 简介 在上一篇文章中,我们列举了flutter中的所有layout类,并且详细介绍了两个非常常用的layout:Row和Column. 掌握了上面两个基本的layout还是不够的,如果需要应付日常的layout使用,我们还需要掌握多一些layout组件.今天我们会介绍一个功能强大的layout:Container layout. Container的使用 Container是一

随机推荐