Flutter学习笔记(27)--数据共享(InheritedWidget)
如需转载,请注明出处: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 = 0; @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 = 0; @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回调的!!!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2016-09-26 Android—PopupWindow的简单使用