Flutter 中是通过 Widget
嵌套 Widget
的方式来构建UI和进行事件处理的,所以记住,Flutter 中万物皆为Widget
。
当 Widget
第一次插入到 Widget
树时会被调用,对于每一个State
对象,Flutter 框架只会调用一次该回调,所以,通常在该回调中做一些一次性的操作,如状态初始化、订阅子树的事件通知等。不能在该回调中调用BuildContext.dependOnInheritedWidgetOfExactType
(该方法用于在 Widget
树上获取离当前 Widget
最近的一个父级InheritedWidget
,关于InheritedWidget
我们稍后介绍,原因是在初始化完成后, Widget
树中的InheritFromWidget
也可能会发生变化,所以正确的做法应该在在build()
方法或didChangeDependencies()
中调用它。
当State
对象的依赖发生变化时会被调用;例如:在之前build()
中包含了一个InheritedWidget
,然后在之后的build()
中InheritedWidget
发生了变化,那么此时InheritedWidget
的子 Widget
的didChangeDependencies()
回调都会被调用。典型的场景是当系统语言 Locale 或应用主题改变时,Flutter 框架会通知 Widget
调用此回调。需要注意,组件第一次被创建后挂载的时候(包括重创建)对应的didChangeDependencies
也会被调用。
此回调读者现在应该已经相当熟悉了,它主要是用于构建 widget 子树的,会在如下场景被调用:
在调用initState()
之后。
在调用didUpdateWidget()
之后。
在调用setState()
之后。
在调用didChangeDependencies()
之后。
在State
对象从树中一个位置移除后(会调用·deactivate·)又重新插入到树的其他位置之后。reassemble()
:此回调是专门为了开发调试而提供的,在热重载(hot reload)时会被调用,此回调在Release模式下永远不会被调用。
在 Widget
重新构建时,Flutter 框架会调用widget.canUpdate
来检测 Widget
树中同一位置的新旧节点,然后决定是否需要更新,如果widget.canUpdate
返回true则会调用此回调。正如之前所述,widget.canUpdate
会在新旧 Widget
的 key 和 runtimeType
同时相等时会返回true,也就是说在在新旧 Widget
的key和runtimeType
同时相等时didUpdateWidget()
就会被调用。
当 State
对象从树中被移除时,会调用此回调。在一些场景下,Flutter 框架会将 State
对象重新插到树中,如包含此 State
对象的子树在树的一个位置移动到另一个位置时(可以通过GlobalKey
来实现)。如果移除后没有重新插入到树中则紧接着会调用dispose()
方法。
当 State
对象从树中被永久移除时调用;通常在此回调中释放资源。
Flutter 提供了一套丰富、强大的基础组件,在基础组件库之上 Flutter 又提供了一套 Material 风格( Android 默认的视觉风格)和一套 Cupertino 风格(iOS视觉风格)的组件库。
基础组件库导入:
1 | import 'package:flutter/widgets.dart'; |
Material(安卓风格)组件,需要先引入它:
1 | import 'package:flutter/material.dart'; |
Cupertino(iOS风格)组件,需要先引入它:
1 | import 'package:flutter/cupertino.dart'; |
由于 Material
和 Cupertino
都是在基础组件库之上的,所以如果我们的应用中引入了这两者之一,则不需要再引入flutter/widgets.dart
了,因为它们内部已经引入过了。
Flutter 的 Widget
类型分为StatefulWidget
和 StatelessWidget
两种,需要深入理解它们的区别,Widget
将是我们构建Flutter应用的基石。
响应式的编程框架中都会有一个永恒的主题——“状态(State)管理”,无论是在 React/Vue
(两者都是支持响应式编程的 Web 开发框架)还是 Flutter 中,他们讨论的问题和解决的思想都是一致的。
管理状态的最常见的方法:
如何决定使用哪种管理方法?下面是官方给出的一些原则可以帮助你做决定:
InheritedWidget
是 Flutter 中非常重要的一个 Widget
,它用于在 Widget
树中共享数据和状态。它提供了一种更高效的方式来将数据传递给子 Widget
,避免直接将数据作为参数一层层传递。下面会详细介绍 InheritedWidget
的作用、用法、以及它的内部机制。
InheritedWidget
主要用于构建 Flutter 应用中的数据共享和状态管理。它的工作原理是通过一个继承自 InheritedWidget
的自定义 Widget
,来封装需要共享的数据。然后,所有需要使用这些数据的子 Widget,可以通过 BuildContext
获取这个 InheritedWidget
中的数据。
Widget
树的上层放置数据源,树中需要访问数据的子 Widget
通过上下文进行访问。Widget
会被重新构建。这是一个必须实现的方法,用于确定当 InheritedWidget 更新时,是否需要通知其依赖的子 Widget。通常会比较新旧数据来决定是否需要更新:
1 |
|
这是一个常见的静态方法,用于在子 Widget 中获取 InheritedWidget
。在实现中,通常会调用 BuildContext
的 dependOnInheritedWidgetOfExactType
方法:
1 | static MyInheritedWidget? of(BuildContext context) { |
Widget
使用,例如用户设置、主题、语言等。setState
重建,尤其在 Widget
树比较深时,可以大大提升性能。InheritedWidget
的工作原理主要基于 Flutter 框架的重建机制。当你调用 dependOnInheritedWidgetOfExactType
时,Flutter 会把当前 Widget
标记为依赖于某个特定的 InheritedWidget
。如果该 InheritedWidget
发生变化(即 updateShouldNotify
返回 true
),Flutter 将会触发依赖的 Widget 重新构建。
InheritedWidget 提供了一种高效且优雅的在 Widget 树中共享数据的方法,避免了直接将数据层层传递的复杂性。通过合理使用 InheritedWidget,可以显著减少不必要的重建,提升应用的性能。
Flutter非常流程新的框架 Provider
实际上是基于 InheritedWidget
进行封装的,是对它的一个高层抽象,目的是简化状态管理。