前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >InheritedWidget使用说明

InheritedWidget使用说明

作者头像
Oceanlong
发布2020-02-24 12:53:39
1.1K0
发布2020-02-24 12:53:39
举报
文章被收录于专栏:移动开发面面观

InheritedWidget

概述

在Flutter进行界面开发时,我们经常会遇到数据传递的问题。由于Flutter采用节点树的方式组织页面,以致于一个普通页面的节点层级会很深。此时,我们如果还是一层层传递数据,当需要修改数据时,就会比较麻烦。

此时,我们需要一种机制,能够让某一个节点下的所有子节点,访问该节点下的数据。

InheritedWidget就满足了我们这一需求。

使用方法

我们创建一个继承InheritedWidget的Widget。

代码语言:javascript
复制
class MyInheritedWidget extends InheritedWidget {
  final int data;

  MyInheritedWidget(@required this.data, Widget child) : super(child: child);

  static MyInheritedWidget getData(BuildContext context) {
    return context.inheritFromWidgetOfExactType(MyInheritedWidget);
  }


  @override
  bool updateShouldNotify(MyInheritedWidget oldWidget) {
    return oldWidget.data != data;
  }


}

可以看到,我们提供了三个方法。

构造方法

InheritedWidget本身是一个没有界面的Widget,或者说是一个代理Widget,我们需要传入我们实际的Widget。

所以,在构造方法中,我们需要传入两个参数,一个是我们希望共享的数据(在本例中数据是int型,实际业务中共享的通常是一个相对复杂的数据),另一个就是我们带界面的Widget。

数据获取方法

代码语言:javascript
复制
  static MyInheritedWidget getData(BuildContext context) {
    return context.inheritFromWidgetOfExactType(MyInheritedWidget);
  }

我们看一下inheritFromWidgetOfExactType方法的源码:

代码语言:javascript
复制
  /// Obtains the nearest widget of the given type, which must be the type of a
  /// concrete [InheritedWidget] subclass, and registers this build context with
  /// that widget such that when that widget changes (or a new widget of that
  /// type is introduced, or the widget goes away), this build context is
  /// rebuilt so that it can obtain new values from that widget.
  
  /// The [aspect] parameter is only used when [targetType] is an
  /// [InheritedWidget] subclasses that supports partial updates, like
  /// [InheritedModel]. It specifies what "aspect" of the inherited
  /// widget this context depends on.
  InheritedWidget inheritFromWidgetOfExactType(Type targetType, { Object aspect });

注释说得很清楚,inheritFromWidgetOfExactType是获取指定context下的,最近的指定类型的Widget,并且此Widget必须是InheritedWidget的子类。

值得注意的是,它是一个静态方法。所以,只要是相同BuildContext我们即可以在任意子节点上,通过这个静态方法,获取到我们的InheritedWidget,然后读取或修改它的共享数据。

更新通知

这个方法,决定了是否通知子节点中StatefulWidgetdidChangeDependencies方法是否调用。

代码语言:javascript
复制
  /// Called when a dependency of this [State] object changes.
  ///
  /// For example, if the previous call to [build] referenced an
  /// [InheritedWidget] that later changed, the framework would call this
  /// method to notify this object about the change.
  ///
  /// This method is also called immediately after [initState]. It is safe to
  /// call [BuildContext.inheritFromWidgetOfExactType] from this method.
  ///
  /// Subclasses rarely override this method because the framework always
  /// calls [build] after a dependency changes. Some subclasses do override
  /// this method because they need to do some expensive work (e.g., network
  /// fetches) when their dependencies change, and that work would be too
  /// expensive to do for every build.
  @protected
  @mustCallSuper
  void didChangeDependencies() { }

StatefulWidget的didChangeDependencies方法就是与InheritedWidget配合使用的。只有当InheritedWidget发生更新并且决定通知时,didChangeDependencies才会调用。

使用场景

通常,当我们需要在Widget树,由父节点向子节点传递数据时,会使用InheritedWidget。一旦某个节点的Widget继承了InheritedWidget,那么它的子节点,不论深度是多少,都可以获取到继承了InheritedWidget的Widget,并取得其中的数据成员。

代码语言:javascript
复制
class TextWidget extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return TextWidgetState();
  }

}

class TextWidgetState extends State<TextWidget> {
  @override
  Widget build(BuildContext context) {
    print("refresh text");
    return Text(
        "count : ${MyInheritedWidget.getData(context).data}"
    );
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    //父或祖先widget中的InheritedWidget改变(updateShouldNotify返回true)时会被调用。
    //如果build中没有依赖InheritedWidget,则此回调不会被调用。
    print("Dependencies change");
  }

}

所以,InheritedWidget适合做某个子树的数据管理Widget。当某个页面、模块或控件依赖一个或一组数据时。我们可以在其上层,创建一个继承了InheritedWidget的数据管理Widget。

通过这样的方式,至少我们不用对数据进行层层传递。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • InheritedWidget
    • 概述
      • 使用方法
        • 构造方法
        • 数据获取方法
        • 更新通知
      • 使用场景
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档