如需转载,请注明出处:Flutter学习笔记(27)--数据共享(InheritedWidget)

InheritedWidget是Flutter中非常重要的一个功能型组件,它提供了一种数据在widget树中从上到下传递、共享的方式,比如我们在应用的根widget中通过InheritedWidget共享了一个数据,那么我们便可以在任意子widget中来获取该共享的数据。

前言:假设有这么一个场景,A、B两个组件,A组件有一个数据data,当A组件中的这个数据data发生变化后,B组件需要跟随着做一些处理操作,这时候,如果不通过广播或其他方式通知B组件,我们有什么办法实现这个功能呢?

didChangeDependencies

在State对象中,有一个didChangeDependencies回调,这个回调会在“依赖”发生变化时被Flutter Framework调用。而这个“依赖”指的是子widget是否用到了父widget中的InheritedWidget共享数据。如果使用了,则代表子widget依赖InheritedWidget,反之如果没有使用则代表没有依赖。这种机制可以使子组件在所依赖的InheritedWidget发生变化时来更新自身。这也就可以实现我们前面所假设的场景了!

接下来先给大家看一下整体的代码和效果截图,心里先有一个大概的概念,带着几个概念去思考:1.依赖 2.didChangeDependencies回调 3.InheritedWidge通过什么来通知子widget

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class FatherWidget extends InheritedWidget {
final int data; FatherWidget({@required this.data, Widget child}) : super(child: child); //子树通过该方法获取共享数据
static FatherWidget getData(BuildContext context) {
return context.inheritFromWidgetOfExactType(FatherWidget);
} //该回调决定当data发生变化时,是否通知子树中依赖data的widget
@override
bool updateShouldNotify(FatherWidget oldWidget) {
return oldWidget.data != data;
}
} class ChildWidget extends StatefulWidget {
@override
_ChildWidgetState createState() => _ChildWidgetState();
} class _ChildWidgetState extends State<ChildWidget> {
@override
Widget build(BuildContext context) {
return new Text(FatherWidget.getData(context).data.toString());
} @override
void didChangeDependencies() {
super.didChangeDependencies();
//父或祖先widget中的InheritedWidget改变(updateShouldNotify返回true)时会被调用
//如果build中没有依赖InheritedWidget,则此回调不会被调用
print("didChangeDependencies = " +
FatherWidget.getData(context).data.toString());
}
} class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _MyAppState();
}
} class _MyAppState extends State<MyApp> {
int count = ; @override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'title',
home: new Scaffold(
appBar: new AppBar(
title: new Text('title'),
),
body: new Center(
child: FatherWidget(
data: count,
child: new Column(
children: <Widget>[
ChildWidget(),
new FloatingActionButton(onPressed: _changeCount,child: new Icon(Icons.adjust),),
],
),
),
),
),
);
} _changeCount() {
setState(() {
++count;
print('mCount == ' + count.toString());
});
}
}

整体代码说明:

点击按钮后会调用_changeCount()方法,方法内给count数加1,然后通知框架重新build,重新build会给FatherWidget内的data重新赋值,data的数据发生了变化,updateShouldNotify会返回true,通知子widget执行didChangeDependencies回调来处理一下响应操作。

分块说明一下实现数据共享都需要哪几步:

1.用于存储共享数据的父Widget,该widget继承InheritedWidget

class FatherWidget extends InheritedWidget {
final int data; FatherWidget({@required this.data, Widget child}) : super(child: child); //子树通过该方法获取共享数据
static FatherWidget getData(BuildContext context) {
return context.inheritFromWidgetOfExactType(FatherWidget);
} //该回调决定当data发生变化时,是否通知子树中依赖data的widget
@override
bool updateShouldNotify(FatherWidget oldWidget) {
return oldWidget.data != data;
}
}

2.子widget,用来处理依赖发生变化时的响应处理操作didChangeDependencies

class ChildWidget extends StatefulWidget {
@override
_ChildWidgetState createState() => _ChildWidgetState();
} class _ChildWidgetState extends State<ChildWidget> {
@override
Widget build(BuildContext context) {
return new Text(FatherWidget.getData(context).data.toString());
} @override
void didChangeDependencies() {
super.didChangeDependencies();
//父或祖先widget中的InheritedWidget改变(updateShouldNotify返回true)时会被调用
//如果build中没有依赖InheritedWidget,则此回调不会被调用
print("didChangeDependencies = " +
FatherWidget.getData(context).data.toString());
}
}

3.FahterWidget和ChildWidget产生依赖关系

  //子树通过该方法获取共享数据
static FatherWidget getData(BuildContext context) {
return context.inheritFromWidgetOfExactType(FatherWidget);
}

4.数据更新,通过setState来重新build

class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _MyAppState();
}
} class _MyAppState extends State<MyApp> {
int count = ; @override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'title',
home: new Scaffold(
appBar: new AppBar(
title: new Text('title'),
),
body: new Center(
child: FatherWidget(
data: count,
child: new Column(
children: <Widget>[
ChildWidget(),
new FloatingActionButton(onPressed: _changeCount,child: new Icon(Icons.adjust),),
],
),
),
),
),
);
} _changeCount() {
setState(() {
++count;
print('mCount == ' + count.toString());
});
}
}

最后需要注意一点,上面说到的依赖前提是两个组件是父、子的关系,我试了一下,如果FatherWidget中没有ChildWidget,只是单纯的使用了FatherWidget的数据的话,是不会触发didChangeDependencies回调的!!!

Flutter学习笔记(27)--数据共享(InheritedWidget)的更多相关文章

  1. Flutter学习笔记(3)--Dart变量与基本数据类型

    一.变量 在Dart里面,变量的声明使用var.Object或Dynamic关键字,如下所示: var name = ‘张三’: 在Dart语言里一切皆为对象,所以如果没有将变量初始化,那么它的默认值 ...

  2. Flutter学习笔记(4)--Dart函数

    如需转载,请注明出处:Flutter学习笔记(4)--Dart函数 Dart是一个面向对象的语言,所以函数也是对象,函数属于Function对象,函数可以像参数一样传递给其他函数,这样便于做回调处理: ...

  3. Flutter学习笔记(5)--Dart运算符

    如需转载,请注明出处:Flutter学习笔记(5)--Dart运算符 先给出一个Dart运算符表,接下来在逐个解释和使用.如下:                            描述       ...

  4. Flutter学习笔记(6)--Dart异常处理

    如需转载,请注明出处:Flutter学习笔记(6)--Dart异常处理 异常是表示发生了意外的错误,如果没有捕获异常,引发异常的隔离程序将被挂起,并且程序将被终止: Dart代码可以抛出并捕获异常,但 ...

  5. Flutter学习笔记(8)--Dart面向对象

    如需转载,请注明出处:Flutter学习笔记(7)--Dart异常处理 Dart作为高级语言,支持面向对象的很多特性,并且支持基于mixin的继承方式,基于mixin的继承方式是指:一个类可以继承自多 ...

  6. Flutter学习笔记(9)--组件Widget

    如需转载,请注明出处:Flutter学习笔记(9)--组件Widget 在Flutter中,所有的显示都是Widget,Widget是一切的基础,我们可以通过修改数据,再用setState设置数据(调 ...

  7. Flutter学习笔记(10)--容器组件、图片组件

    如需转载,请注明出处:Flutter学习笔记(10)--容器组件.图片组件 上一篇Flutter学习笔记(9)--组件Widget我们说到了在Flutter中一个非常重要的理念"一切皆为组件 ...

  8. Flutter学习笔记(11)--文本组件、图标及按钮组件

    如需转载,请注明出处:Flutter学习笔记(10)--容器组件.图片组件 文本组件 文本组件(text)负责显示文本和定义显示样式,下表为text常见属性 Text组件属性及描述 属性名 类型 默认 ...

  9. Flutter学习笔记(12)--列表组件

    如需转载,请注明出处:Flutter学习笔记(12)--列表组件 在日常的产品项目需求中,经常会有列表展示类的需求,在Android中常用的做法是收集数据源,然后创建列表适配器Adapter,将数据源 ...

随机推荐

  1. FZU 2235

    中文题,题意略. 这个题点少坐标范围大,直接离散化后建图搞. 这个题目卡vector,真是一脸懵逼............ #include<stdio.h> #include<st ...

  2. Leetcode之广度优先搜索(BFS)专题-详解429. N叉树的层序遍历(N-ary Tree Level Order Traversal)

    Leetcode之广度优先搜索(BFS)专题-429. N叉树的层序遍历(N-ary Tree Level Order Traversal) 给定一个 N 叉树,返回其节点值的层序遍历. (即从左到右 ...

  3. Leetcode之回溯法专题-47. 全排列 II(Permutations II)

    Leetcode之回溯法专题-47. 全排列 II(Permutations II) 给定一个可包含重复数字的序列,返回所有不重复的全排列. 示例: 输入: [1,1,2] 输出: [ [1,1,2] ...

  4. Oracle批量更改所有表的字段取值_类型_原字段名

    CREATE PROCEDURE 存储过程名称 is cursor c_tab is select * from user_tab_columns t r_tab user_tab_columns%r ...

  5. NLP(十二)指代消解

    代词是用来代替重复出现的名词 例句: 1.Ravi is a boy. He often donates money to the poor. 先出现主语,后出现代词,所以流动的方向从左到右,这类句子 ...

  6. 小米 OJ 编程比赛 02 月常规赛 3 Logic Gatekeeper CDQ分治

    link:https://code.mi.com/problem/list/view?id=139 题意: 有一个1e6 * 1e6 大的格子,现在有两种操作:1,给一个子矩阵中的每个格子加上k.2, ...

  7. cogs2823求组合数(lucas定理

    http://cogs.pro:8080/cogs/problem/problem.php?pid=vNQJJVUVj 再写个数学水题,其实lucas适用于m,n比较大而p比较小的情况. 题意:给出两 ...

  8. Three.js 开发机房(四)

    这一节我们讲讲怎么画机柜,其实机柜如果作的复杂一点.逼真一点可以用3D建模工具,不过一般的项目中也不用做的那么麻烦,那我们就可以将机柜抽象以下,首先它是一块具有长宽高的立方体铁块,然后我们从中间在掏掉 ...

  9. erlang加密模块crypto的一些使用

    crypto 模块描述:该模块提供一系列加密函数: 散列函数-安全散列标准,MD5报文摘要算法(RFC 1321)和MD4报文摘要算法(RFC 1320); Hmac函数-散列消息认证(RFC 210 ...

  10. Docker Swarm从部署到基本操作

    关于Docker Swarm Docker Swarm由两部分组成: Docker集群:将一个或多个Docker节点组织起来,用户就能以集群的方式进行管理: 应用编排:有一套API用来部署和管理容器: ...