共享状态管理-InheritedWidget的简单使用
InheritedWidget
是 Flutter 中非常重要的一个功能型组件,它提供了一种在 widget 树中从上到下共享数据的方式,
InheritedWidge
t和React
中的context
功能类似,可以实现跨组件数据的传递。InheritedWidget
的在 widget 树中数据传递方向是从上到下的。
先查看InheritedWidget
源码,
- InheritedWidget 的构造中需要传入 child,这个child就是需要使用共享数据的子widget
- updateShouldNotify 这个抽象方法需要子类实现
abstract class InheritedWidget extends ProxyWidget {
/// Abstract const constructor. This constructor enables subclasses to provide
/// const constructors so that they can be used in const expressions.
const InheritedWidget({
super.key, required super.child });
InheritedElement createElement() => InheritedElement(this);
/// Whether the framework should notify widgets that inherit from this widget.
///
/// When this widget is rebuilt, sometimes we need to rebuild the widgets that
/// inherit from this widget but sometimes we do not. For example, if the data
/// held by this widget is the same as the data held by `oldWidget`, then we
/// do not need to rebuild the widgets that inherited the data held by
/// `oldWidget`.
///
/// The framework distinguishes these cases by calling this function with the
/// widget that previously occupied this location in the tree as an argument.
/// The given widget is guaranteed to have the same [runtimeType] as this
/// object.
bool updateShouldNotify(covariant InheritedWidget oldWidget);
}
来定义 “计数器”示例应用程序一个共享数据的InheritedWidget
,需要继承自 InheritedWidget
, 如下:
class CounterWidget extends InheritedWidget {
// 1.需要共享的数据
final int counter;
// 2.定义构造方法 传入最新的 counter值
CounterWidget({
this.counter, Widget child}): super(child: child);
// 3.获取组件最近的当前InheritedWidget
static CounterWidget of(BuildContext context) {
// 沿着Element树, 去找到最近的CounterElement, 从Element中取出Widget对象
return context.dependOnInheritedWidgetOfExactType();
}
// 4.绝对要不要回调State中的didChangeDependencies
// 如果返回true: 执行依赖当期的InheritedWidget的State中的 didChangeDependencies
bool updateShouldNotify(CounterWidget oldWidget) {
return oldWidget.counter != counter;
}
}
-
需要共享的数据 为 int 类型的 counter
-
在构造中给counter 赋值,child 是需要使用数据的widget
-
定义了一个of方法,该方法通过context开始去查找祖先的
CounterWidget
-
updateShouldNotify
方法是对比新旧CounterWidget
,是否需要对更新相关依赖的Widget如果返回true: 执行依赖当期的InheritedWidget的State中的
didChangeDependencies
在示例中去使用CounterWidget
, 定义 ShowDataWidget 子组件使用共享的数据:
class _HomePageState extends State<HomePage> {
int _counter = 100;
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("InheritedWidget"),
),
body: CounterWidget(//使用CounterWidget 将需要使用数据widget包裹
counter: _counter,
child: Center(
child: ShowDataWidget(),//在ShowDataWidget 中去使用共享的数据
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
setState(() {
_counter++;
});
},
),
);
}
}
class ShowDataWidget extends StatefulWidget {
_ShowDataWidgetState createState() => _ShowDataWidgetState();
}
class _ShowDataWidgetState extends State<ShowDataWidget> {
void didChangeDependencies() {
super.didChangeDependencies();
print("执行了ShowDataWidget中的didChangeDependencies");
}
Widget build(BuildContext context) {
int counter = CounterWidget.of(context).counter;
return Card(
color: Colors.red,
child: Text("当前计数: $counter", style: TextStyle(fontSize: 30),),CounterWidget
);
}
}
我们可以看到:
-
这里 按下floatingActionButton 之后 ,调用setState 重新调用_HomePageState的 build 方法,然后重新创建
CounterWidget
传入最新的counter 值。 -
在
ShowDataWidget
中 通过调用CounterWidget
中的 **of **方法 获取CounterWidget
实例,得到共享数据counterint counter = CounterWidget.of(context).counter;
-
我们看到
_ShowDataWidgetState
中的didChangeDependencies
方法被调用关于
didChangeDependencies
方法 会在“依赖”发生变化时被Flutter 框架调用。而这个“依赖”指的就是子 widget 是否使用了父 widget 中InheritedWidget的数据!如果使用了,则代表子 widget 有依赖;如果没有使用则代表没有依赖。这种机制可以使子组件在所依赖的InheritedWidget变化时来更新自身!比如当主题、locale(语言)等发生变化时,依赖其的子 widget 的didChangeDependencies方法将会被调用.2022-11-09 13:11:06.175 14203-14233/com.example.learn_flutter I/flutter: 执行了_ShowData01State中的didChangeDependencies 2022-11-09 13:11:07.383 14203-14233/com.example.learn_flutter I/flutter: 执行了_ShowData01State中的didChangeDependencies 2022-11-09 13:11:08.248 14203-14233/com.example.learn_flutter I/flutter: 执行了_ShowData01State中的didChangeDependencies 2022-11-09 13:11:08.999 14203-14233/com.example.learn_flutter I/flutter: 执行了_ShowData01State中的didChangeDependencies
效果如下: