[- Flutter 数据&状态篇 -] InheritedWidget
时间:2022-07-27
本文章向大家介绍[- Flutter 数据&状态篇 -] InheritedWidget,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
一个界面是由众多组件拼组而成。经常需要将一个组件进行封装,但此时有一个问题,如何让多个组件去共享一些值。
比如下面在一个_State中使用了WidgetA组件,传入_incrementCounter自加的方法和_counter计数值。 WidgetA又是由下面若干个自定义的Widget组成。那么问题来了,WidgetK点击时如何让WidgetE中的值+1? 一个最直接的方法就是通过构造函数将变量和函数一层层向下传递。你也许会说WTF,你好像在逗我笑?
1.现在来模拟一下这个情景
将计数器的页面分成五个部分,分别用一个Widget来控制。
WidgetA:控制视图总体显示 依赖WidgetB和WidgetF
WidgetB:控制视图布局排布 依赖WidgetC
WidgetC:控制视图内容组成 依赖WidgetD
WidgetD:控制视图计数器使用
WidgetF:控制视图触发计数
现在要让WidgetF的点击被WidgetD响应,下面是最笨的解决方案:构造传参,一层层传递。虽然麻烦,但又不是不能用。
class _MyHomePageState extends State {
int _counter = 0;
@override
Widget build(BuildContext context) {
return WidgetA(_counter,_incrementCounter,widget.title);
}
void _incrementCounter() {
setState(() {
_counter++;
});
}
}
class WidgetA extends StatelessWidget {
WidgetA(this.counter,this.increment,this.title);
final int counter;
final VoidCallback increment;
final String title;
@override
Widget build(BuildContext context) {
var result= Scaffold(
appBar: AppBar(title: Text(title),),
body: WidgetB(counter),
floatingActionButton: WidgetF(increment),
);
return result;
}
}
class WidgetB extends StatelessWidget {
WidgetB(this.counter);
final int counter;
@override
Widget build(BuildContext context) {
var center= Center(
child: WidgetC(counter),
);
return center;
}
}
class WidgetC extends StatelessWidget {
WidgetC(this.counter);
final int counter;
@override
Widget build(BuildContext context) {
var column=Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('You have pushed the button this many times:',),
WidgetD(counter)
],
);
return column;
}
}
class WidgetD extends StatelessWidget {
WidgetD(this.counter);
final int counter;
@override
Widget build(BuildContext context) {
var text= Text('$counter', style: Theme.of(context).textTheme.display1,);
return text;
}
}
class WidgetF extends StatelessWidget {
WidgetF(this.increment);
final VoidCallback increment;
@override
Widget build(BuildContext context) {
var button= FloatingActionButton(
onPressed: increment,
tooltip: 'Increment',
child: Icon(Icons.add),
);
return button;
}
}
是不是感觉非常麻烦呢? 如何处理这种情况,能让需要的参数不这么跋山涉水?
2.第一个解决方案:InheritedWidget
这里我们使用一个InheritedWidget来提供数据和方法,让她们共享与五个组件之中。就像下面这样,将值存储于一个InheritedWidget中,随用随取。这样世界终于清静了,不用构造传值满天飞。
/// 数据模型
class CountModel {
final int count;//计数器
final VoidCallback increment;//增长函数
const CountModel(this.count,this.increment);
}
class CountWidget extends InheritedWidget {
final CountModel model;
CountWidget({
Key key,
@required this.model,
@required Widget child,
}) : super(key: key, child: child);
static CountWidget of(BuildContext context) {//提供数据模型方法
return context.inheritFromWidgetOfExactType(CountWidget);
}
//是否重建widget就取决于数据是否相同
@override
bool updateShouldNotify(CountWidget oldWidget) {
return model.count != oldWidget.model.count;
}
}
再看一下现在每个子组件的实现,就无需把需要的参数一层层往下传。 如果你的封装层级较深,InheritedWidget将是你数据传递的好帮手。
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State {
int _counter = 0;
@override
Widget build(BuildContext context) {
return
CountWidget(child: WidgetA(widget.title),model: CountModel(_counter, _incrementCounter),);
}
void _incrementCounter() {
setState(() {
_counter++;
});
}
}
class WidgetA extends StatelessWidget {
WidgetA(this.title);
final String title;
@override
Widget build(BuildContext context) {
var result= Scaffold(
appBar: AppBar(title: Text(title),),
body: WidgetB(),
floatingActionButton: WidgetF(),
);
return result;
}
}
class WidgetB extends StatelessWidget {
@override
Widget build(BuildContext context) {
var center= Center(
child: WidgetC(),
);
return center;
}
}
class WidgetC extends StatelessWidget {
@override
Widget build(BuildContext context) {
var column=Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('You have pushed the button this many times:',),
WidgetD()
],
);
return column;
}
}
class WidgetD extends StatelessWidget {
@override
Widget build(BuildContext context) {
var counter= CountWidget.of(context).model.count;
var text= Text('$counter', style: Theme.of(context).textTheme.display1,);
return text;
}
}
class WidgetF extends StatelessWidget {
@override
Widget build(BuildContext context) {
var increment= CountWidget.of(context).model.increment;
var button= FloatingActionButton(
onPressed: increment,
tooltip: 'Increment',
child: Icon(Icons.add),
);
return button;
}
}
- Spring实战——XML和JavaConfig的混合配置
- ambari安装指南
- Spring实战——通过Java代码装配bean
- WCF技术剖析之三十一: WCF事务编程[中篇]
- Spring实战——无需一行xml配置实现自动化注入
- 基于改进人工蜂群算法的K均值聚类算法(附MATLAB版源代码)
- RabbitMQ入门-Routing直连模式
- WCF技术剖析之三十二:一步步创建一个完整的分布式事务应用
- .NET的资源并不限于.resx文件,你可以采用任意存储形式[上篇]
- RabbitMQ入门-消息订阅模式
- 年终盘点:2018最值得学习的几种热门编程语言
- 如何编写没有Try/Catch的程序
- RabbitMQ入门-消息派发那些事儿
- RabbitMQ入门-高效的Work模式
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 卧槽,又一款 Markdown 组合神器!!!
- SQL-查询各工程项目使用所提供零件最多的供应商
- 浙大版《C语言程序设计(第3版)》题目集 习题8-3 数组循环右移
- SwiftUI:控制图像插值
- SQL-查询比p6零件供应数量都高的零件
- 浙大版《C语言程序设计(第3版)》题目集 习题8-5 使用函数实现字符串部分复制
- 最小生成树-Magicpig密室出逃(Kruskal+并查集)
- 浙大版《C语言程序设计(第3版)》题目集 习题8-6 删除字符
- SQL-显示供应商供应零件的汇总列表(with rollup+coalesce)
- 浙大版《C语言程序设计(第3版)》题目集 习题8-8 判断回文字符串
- 双向广搜-HDU1401 Solitaire
- TCP三次握手和四次挥手以及11种状态
- 浙大版《C语言程序设计(第3版)》题目集 题8-9 分类统计各类字符个数
- 迭代加深搜索-POJ 3134 Power Calculus
- 浙大版《C语言程序设计(第3版)》题目集 习题9-2 计算两个复数之积