【每日 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 Widget 解析
|
2天前
|
存储 容器
Flutter 有状态Widget 和 无状态Widget
Flutter 有状态Widget 和 无状态Widget
|
1月前
深入理解Flutter鸿蒙next版本 中的Widget继承:使用extends获取数据与父类约束
本文详细介绍了Flutter中如何通过继承其他Widget来创建自定义组件。首先解释了Widget继承的基本概念,包括StatelessWidget和StatefulWidget的区别。接着通过具体示例展示了如何继承StatelessWidget和StatefulWidget,并在子类中访问父类的build方法和状态。最后,结合多个自定义Widget展示了如何在实际应用中灵活使用继承和组合来构建复杂的UI。
76 8
|
1月前
|
容器
flutter&鸿蒙next 使用 InheritedWidget 实现跨 Widget 传递状态
在 Flutter 中,状态管理至关重要。本文详细介绍了如何使用 InheritedWidget 实现跨 Widget 的状态传递。InheritedWidget 允许数据在 Widget 树中向下传递,适用于多层嵌套的场景。通过一个简单的计数器示例,展示了如何创建和使用 InheritedWidget,包括其基础概念、工作原理及代码实现。虽然 InheritedWidget 较底层,但它是许多高级状态管理解决方案的基础。
103 2
|
2月前
|
容器
flutter:第一个flutter&Widget的使用 (二)
本文介绍了Flutter框架下的基本组件及其用法,包括简单的 Stateless Widget 如文本和按钮,以及更复杂的 StatefulWidget 示例。详细解释了如何使用 `context` 获取祖先小部件的信息,并展示了 `MaterialApp` 的属性及用途。此外,还探讨了 `StatefulWidget` 与 `StatelessWidget` 的区别,以及 `AppBar` 的常见属性配置方法。适合Flutter初学者参考学习。
|
1月前
|
Dart JavaScript 前端开发
Flutter 的 Widget 概述与常用 Widgets 与鸿蒙 Next 的对比
Flutter 是 Google 开发的开源 UI 框架,用于快速构建高性能的移动、Web 和桌面应用。Flutter 通过 Widget 构建 UI,每个 UI 元素都是 Widget,包括文本、按钮、图片等。Widget 不仅描述外观,还描述行为,是不可变的。常见的 Widget 包括结构型(Container、Column、Row)、呈现型(Text、Image)、交互型(ElevatedButton)和状态管理型(StatefulWidget)。Flutter 与鸿蒙 Next 在组件化架构、开发语言、布局系统、性能和跨平台支持方面各有优势
75 0
|
5月前
Flutter-底部弹出框(Widget层级)
文章描述了如何在Flutter中使用DraggableScrollableSheet创建一个底部弹出框,同时保持其可手势滑动关闭。作者遇到问题并提出对原控件进行扩展,以支持头部和列表布局的滑动关闭功能。
199 0
|
6月前
Flutter StreamBuilder 实现局部刷新 Widget
Flutter StreamBuilder 实现局部刷新 Widget
52 0
|
7月前
|
Android开发
Flutter完整开发实战详解(六、 深入Widget原理),2024百度Android岗面试真题收录解析
Flutter完整开发实战详解(六、 深入Widget原理),2024百度Android岗面试真题收录解析
|
7月前
|
开发框架 前端开发 搜索推荐
【Flutter前端技术开发专栏】Flutter中的自定义Widget与渲染流程
【4月更文挑战第30天】探索Flutter的自定义Widget与渲染流程。自定义Widget是实现复杂UI设计的关键,优点在于个性化设计、功能扩展和代码复用,但也面临性能优化和复杂性管理的挑战。创建步骤包括设计结构、定义Widget类、实现构建逻辑和处理交互。Flutter渲染流程涉及渲染对象树、布局、绘制和合成阶段。实践案例展示如何创建带渐变背景和阴影的自定义按钮。了解这些知识能提升应用体验并应对开发挑战。查阅官方文档以深入学习。
86 0
【Flutter前端技术开发专栏】Flutter中的自定义Widget与渲染流程