经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » Android » 查看文章
Flutter学习笔记(27)--数据共享(InheritedWidget)
来源:cnblogs  作者:CurtisWgh  时间:2019/9/27 9:35:52  对本文有异议

如需转载,请注明出处: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 

  1. import 'package:flutter/material.dart';
  2. void main() => runApp(MyApp());
  3. class FatherWidget extends InheritedWidget {
  4. final int data;
  5. FatherWidget({@required this.data, Widget child}) : super(child: child);
  6. //子树通过该方法获取共享数据
  7. static FatherWidget getData(BuildContext context) {
  8. return context.inheritFromWidgetOfExactType(FatherWidget);
  9. }
  10. //该回调决定当data发生变化时,是否通知子树中依赖data的widget
  11. @override
  12. bool updateShouldNotify(FatherWidget oldWidget) {
  13. return oldWidget.data != data;
  14. }
  15. }
  16. class ChildWidget extends StatefulWidget {
  17. @override
  18. _ChildWidgetState createState() => _ChildWidgetState();
  19. }
  20. class _ChildWidgetState extends State<ChildWidget> {
  21. @override
  22. Widget build(BuildContext context) {
  23. return new Text(FatherWidget.getData(context).data.toString());
  24. }
  25. @override
  26. void didChangeDependencies() {
  27. super.didChangeDependencies();
  28. //父或祖先widget中的InheritedWidget改变(updateShouldNotify返回true)时会被调用
  29. //如果build中没有依赖InheritedWidget,则此回调不会被调用
  30. print("didChangeDependencies = " +
  31. FatherWidget.getData(context).data.toString());
  32. }
  33. }
  34. class MyApp extends StatefulWidget {
  35. @override
  36. State<StatefulWidget> createState() {
  37. return _MyAppState();
  38. }
  39. }
  40. class _MyAppState extends State<MyApp> {
  41. int count = 0;
  42. @override
  43. Widget build(BuildContext context) {
  44. return new MaterialApp(
  45. title: 'title',
  46. home: new Scaffold(
  47. appBar: new AppBar(
  48. title: new Text('title'),
  49. ),
  50. body: new Center(
  51. child: FatherWidget(
  52. data: count,
  53. child: new Column(
  54. children: <Widget>[
  55. ChildWidget(),
  56. new FloatingActionButton(onPressed: _changeCount,child: new Icon(Icons.adjust),),
  57. ],
  58. ),
  59. ),
  60. ),
  61. ),
  62. );
  63. }
  64. _changeCount() {
  65. setState(() {
  66. ++count;
  67. print('mCount == ' + count.toString());
  68. });
  69. }
  70. }

 整体代码说明:

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

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

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

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

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

  1. class ChildWidget extends StatefulWidget {
  2. @override
  3. _ChildWidgetState createState() => _ChildWidgetState();
  4. }
  5. class _ChildWidgetState extends State<ChildWidget> {
  6. @override
  7. Widget build(BuildContext context) {
  8. return new Text(FatherWidget.getData(context).data.toString());
  9. }
  10. @override
  11. void didChangeDependencies() {
  12. super.didChangeDependencies();
  13. //父或祖先widget中的InheritedWidget改变(updateShouldNotify返回true)时会被调用
  14. //如果build中没有依赖InheritedWidget,则此回调不会被调用
  15. print("didChangeDependencies = " +
  16. FatherWidget.getData(context).data.toString());
  17. }
  18. }

3.FahterWidget和ChildWidget产生依赖关系

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

 

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

  1. class MyApp extends StatefulWidget {
  2. @override
  3. State<StatefulWidget> createState() {
  4. return _MyAppState();
  5. }
  6. }
  7. class _MyAppState extends State<MyApp> {
  8. int count = 0;
  9. @override
  10. Widget build(BuildContext context) {
  11. return new MaterialApp(
  12. title: 'title',
  13. home: new Scaffold(
  14. appBar: new AppBar(
  15. title: new Text('title'),
  16. ),
  17. body: new Center(
  18. child: FatherWidget(
  19. data: count,
  20. child: new Column(
  21. children: <Widget>[
  22. ChildWidget(),
  23. new FloatingActionButton(onPressed: _changeCount,child: new Icon(Icons.adjust),),
  24. ],
  25. ),
  26. ),
  27. ),
  28. ),
  29. );
  30. }
  31. _changeCount() {
  32. setState(() {
  33. ++count;
  34. print('mCount == ' + count.toString());
  35. });
  36. }
  37. }

 

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

 

原文链接:http://www.cnblogs.com/upwgh/p/11593294.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号