【每日 widget】 Flutter InheritedWidget

简介: 【每日 widget】 Flutter InheritedWidget

image.png


InheritedWidget 介绍

InheritedWidget 可以让 child 共享数据。

每个 Widget 生成的 Element 挂载到 Element Tree 上的时候都会调用 mount方法,mount 方法会调用_updateInheritance方法。

void _updateInheritance() {
    assert(_lifecycleState == _ElementLifecycle.active);
    _inheritedWidgets = _parent?._inheritedWidgets;
  }
复制代码

非 InheritedElement 直接传递 _parent 的 _inheritedWidgets

void _updateInheritance() {
    assert(_lifecycleState == _ElementLifecycle.active);
    final Map<Type, InheritedElement>? incomingWidgets = _parent?._inheritedWidgets;
    if (incomingWidgets != null) {
      _inheritedWidgets = HashMap<Type, InheritedElement>.of(incomingWidgets);
    } else {
      _inheritedWidgets = HashMap<Type, InheritedElement>();
    }
    _inheritedWidgets![widget.runtimeType] = this;
  }
复制代码

InheritedElement copy _parent 的 _inheritedWidgets 做为独产的一份保留起来。为什么要 copy一份呢,是为了实现这样的效果:InheritedElement 只影响他的 child,不会影响到 parent。如果不 copy 的话,就会影响到 parent 了。所以 child 只会找到离他最近的 InheritedElement。

如果只是想获取数据,不触发更新,用 getElementForInheritedWidgetOfExactType,否则用 dependOnInheritedWidgetOfExactType。

dependOnInheritedWidgetOfExactType 同时会注册依赖的 element,方便后续更新。

总结一下

  • 在当前组件的 mount 和 activate 阶段,系统调用  _updateInheritance 方法,将 InheritedWidget 类型的父组件添加到  _inheritedWidgets 集合中。
  • 子组件执行 dependOnInheritedWidgetOfExactType 方法时,从  _inheritedWidgets 集合中获取指定 InheritedWidget 类型的父组件,并将当前组件注册到 InheritedWidget 类型父组件的  _dependents 集合中。
  • InheritedWidget 组件数据发生变化(updateShouldNotify 方法返回true),重建时,InheritedWidget 组件遍历  _dependents 集合中所有依赖的子组件,执行子组件的 didChangeDependencies 的方法。

使用 InheritedWidget

InheritedWidget 用处就是可以让 child 获得到共享数据。至于 触发 didChangeDependencies 这个逻辑 一般情况下用不到。更新 InheritedWidget 数据可以用 setState 的方式,但是这样会导致整棵树都更新。 有两种办法可以避免整体更新。

  1. 用 const 关键字修改 child。但这种做法并不能总是可以成功,因为child 可能不可以被 const 修饰。
  2. 提升不需要 rebuild的 child 到 InheritedWidget 父级。

我们可以把 InheritedWidget 的 data 换成 ValueNotifier,当数据变化的时候直接修改值,监听 data 的 widget 才会更新,其它 widget 不会更新。

触发 didChangeDependencies 的意义

使用 InheritedWidget 的过程中我们发现,要么 setState,鉵发全体更新,要么不用 setState ,用 ValueNotifier 触发。那么 InheritedWidget 特意触发 didChangeDependencies 有什么意义呢?

意义在于当依赖的数据变化时,需要进行一个耗时操作或异步操作,这个操作不适合放在 build 方法里。那么放在 didChangeDependencies 就是唯一的选择。

InheritedWidget 的孩子们

  • InheritedNotifier。他的作用是当 value 变化的时候自动rebuild 。rebuild 跳过了 widget 的 rebuild,直接 rebuild  element ,算是优化吧。但是会整体 rebuild ,不能选择 subTree rebuild。
  • InheritedModel。他的作用是可以选择 rebuild  subtree。rebuild 的时候是连 widget 一起 rebbuild 的。但是他的 rebuild 优化 是有条件的,child 必须加 const 关键字,否则所有 child 都会 rebuild。

方案讨论

其实页面不是很复杂的情况下,整体 rebuild 也没什么问题,只要不是很频繁,可以用 InheritedNotifier 。如果有一部分变化非常频繁,可以考虑用 InheritedModel。但只能控制到 model 相关的子树,子树往下可能会全部 rebuild。

要想精确控制可以把 InheritedWidget 的数据换成 ValueNotifier。InheritedWidget 的作用仅仅是传递 ValueNotifier,不会主动触发 rebuild。需要 rebuild 的地方自行监听 ValueNotifier,这样就可以做到精准 rebuild 了。ValueNotifier 的值可以是简单的 int ,也可以是自定义的类。如果是自定义的类会更灵活些。child 可以修改数据, 修改过的数据可以在整个 InheritedWidget 树中共享。

目录
相关文章
|
2月前
Flutter-底部弹出框(Widget层级)
文章描述了如何在Flutter中使用DraggableScrollableSheet创建一个底部弹出框,同时保持其可手势滑动关闭。作者遇到问题并提出对原控件进行扩展,以支持头部和列表布局的滑动关闭功能。
129 0
|
3月前
Flutter StreamBuilder 实现局部刷新 Widget
Flutter StreamBuilder 实现局部刷新 Widget
28 0
|
4月前
|
Android开发
Flutter完整开发实战详解(六、 深入Widget原理),2024百度Android岗面试真题收录解析
Flutter完整开发实战详解(六、 深入Widget原理),2024百度Android岗面试真题收录解析
|
4月前
|
JavaScript 前端开发 开发者
【Flutter前端技术开发专栏】Flutter中的Widget与状态管理
【4月更文挑战第30天】本文探讨了Flutter的Widget和状态管理。Widget是Flutter构建UI的基础,分为有状态和无状态两种。状态管理确保UI随应用状态变化更新,影响应用性能和可维护性。文章介绍了`setState`、`Provider`、`Riverpod`、`Bloc`和`Redux`等状态管理方法,并通过计数器应用展示了其实现。选择合适的状态管理策略对高效开发至关重要。
59 0
【Flutter前端技术开发专栏】Flutter中的Widget与状态管理
|
4月前
|
编解码 算法 开发者
Flutter的布局系统:深入探索布局Widget与布局原则
【4月更文挑战第26天】Flutter布局系统详解,涵盖布局Widget(Row/Column、Stack、GridView/ListView、CustomSingleChildLayout)和布局原则(弹性布局、约束优先、流式布局、简洁明了)。文章旨在帮助开发者理解并运用Flutter的布局系统,创建适应性强、用户体验佳的界面。通过选择合适的布局Widget和遵循原则,可实现复杂且高效的UI设计。
|
4月前
|
前端开发 开发者 UED
Flutter的自定义Painter:深入探索自定义绘制Widget的技术实现
【4月更文挑战第26天】Flutter的自定义Painter允许开发者根据需求绘制独特UI,通过继承`CustomPaint`类和重写`paint`方法实现。在`paint`中使用`Canvas`绘制图形、路径等。创建自定义Painter类后,将其作为`CustomPaint` Widget的`painter`属性使用。此技术可实现自定义形状、渐变、动画等复杂效果,提升应用视觉体验。随着Flutter的进化,自定义Painter将提供更丰富的功能。
|
4月前
|
开发框架 搜索推荐 Android开发
Flutter的Widget基础:概念、分类与深入探索
【4月更文挑战第26天】Flutter Widget详解:基础、分类与工作原理。Widget是Flutter UI的核心,描述界面外观而非直接渲染。分为基础、布局、可滚动及状态管理四大类。基于响应式编程,状态变化时自动更新UI。了解其概念、分类和原理,能助开发者高效构建精美应用。随着Flutter生态发展,Widget系统潜力无限。
Flutter源码分析笔记:Widget类源码分析
本文记录阅读与分析Flutter源码 - Widget类源码分析。
84 0
Flutter源码分析笔记:Widget类源码分析
|
Dart 前端开发 开发工具
谷歌移动UI框架Flutter教程之Widget
谷歌移动UI框架Flutter教程之Widget
|
API Android开发 容器
Flutter控件之基类Widget封装
基类的Widget主要确定以下几个方面,第一就是,自定义一个抽象类还是非抽象类,第二、继承方式,采取有状态还是无状态,第三、关于组件的点击方式,如何进行实现。
150 0