如需转载,请注明出处: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. Linux面试题总结

    1.简述Apache两种工作模式,以及它们之间的区别.答:(1)prefork MPM使用多个子进程,每个子进程只有一个线程来处理一个http请求,直到这个TCP连接被释放.root主进程在最初建立s ...

  2. c3p0,dbcp与druid 三大连接池的区别[转]

    说到druid,这个是在开源中国开源项目中看到的,说是比较好的数据连接池.于是乎就看看.扯淡就到这. 下面就讲讲用的比较多的数据库连接池.(其实我最先接触的是dbcp这个) 1)DBCP DBCP是一 ...

  3. netty源码解解析(4.0)-20 ChannelHandler: 自己实现一个自定义协议的服务器和客户端

    本章不会直接分析Netty源码,而是通过使用Netty的能力实现一个自定义协议的服务器和客户端.通过这样的实践,可以更深刻地理解Netty的相关代码,同时可以了解,在设计实现自定义协议的过程中需要解决 ...

  4. Flink 源码解析 —— TaskManager 处理 SubmitJob 的过程

    TaskManager 处理 SubmitJob 的过程 https://t.zsxq.com/eu7mQZj 博客 1.Flink 从0到1学习 -- Apache Flink 介绍 2.Flink ...

  5. P1415 拆分数列 DP

    传送门: 题意: 将一个数字串分成许多不同的小串,使得这些小串代表的数字严格递增,要求最后一个数字尽可能地小. 然后满足字典序尽可能大. 思路: 由于最后一个数字要尽可能地小,所以先处理出每个数的L[ ...

  6. hdu 4825 Xor Sum(01字典树模版题)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4825 题解:一到01字典树的模版题,01字典树就是就是将一些树用二进制放到一个树上这样可以方便对整体异 ...

  7. uva 796 C - Critical Links(tarjan求桥)

    题目链接:https://vjudge.net/contest/67418#problem/C 题意:求出桥的个数并且按顺序输出 题解:所谓桥就是去掉这条边后连通块增加,套用一下模版就行. #incl ...

  8. Array List和Linked List实现分析

    一,前言 ​ 先来一张Collection集合图. ​ 今天分享一些关于Collection集合中的List,讲真的集合这东西在网上真是老生常谈了.说实话连本人都觉得腻了(哈哈),但是话又说回来,整个 ...

  9. 在javascript中的浏览器兼容问题以及兼容浏览器汇总(默认事件,阻止冒泡,事件监听。。。)以及解决方式详解

    在javascript中常见的浏览器兼容问题,以及解决方式. 在前端工作当中我们遵循这样的原则:渐进增强和优雅降级   渐进增强(progressive enhancement): 针对低版本浏览器进 ...

  10. JPA案例

    ORM 什么是ORM: 对象关系映射(Object Relational Mapping,简称ORM)是建立实体类和数据库表之间的关系,从而达到操作实体类就相当于操作数据库表的目的. ORM思想 主要 ...