在Flutter中如何在不同的Widget
传递数据?如果只是简单的上下级关系,我们可以把数据添加到下级的Widget
的函数中。但是如果传递数据的Widget
层级相隔太远,那么不可能一层一层传递。Flutter提供了一种在Widget
树中自上而下传递数据的方法InheritedWidget
。
- 使用
InheritedWidget
因为InheritedWidget
是一个抽象类,所以需要创建一个扩展它的类。
扩展InheritedWidget
需要覆盖updateShouldNotify
方法。那么什么是updateShouldNotify
方法:
updateShouldNotify
用于控制依赖于该InheritedWidget
的组件是否需要重建。如果updateShouldNotify
的值是true
,则当InheritedWidget
发生变化时,依赖于该InheritedWidget
的Widget
会被重建,其元素的didChangeDependencies
函数会被调用,从而更新子Widget
中的显示。反之,则不会重建依赖于该InheritedWidget
的Widget
。
bool updateShouldNotify(covariant InheritedWidget oldWidget);
- 实现of方法
of
约定是在InheritedWidget
上提供一个静态方法,该方法 调用BuildContext.dependOnInheritedWidgetOfExactType
。
下面是一个名为Info
的类,继承InheritedWidget
。它覆盖updateShouldNotify
并有一个静态方法of
。
class Info extends InheritedWidget {
final int score;//需要在子树中共享的数据
const Info({
Key? key,
required this.score,
required Widget child,
}) : super(key: key,child: child);
//创建Info方法从子树中的widget获取共享数据
static Info? of(BuildContext context){
return context.dependOnInheritedWidgetOfExactType<Info>();
}
//该回调决定当data发生变化时,是否通知子树中依赖data的Widget重新build
@override
bool updateShouldNotify(covariant Info oldWidget){
return score != oldWidget.score;
}
}
- 调用of方法
使用该of
方法时,context
必须是 InheritedWidget
的后代,这意味着它必须在树中的InheritedWidget
“下方”。
下面创建名为CurrentScore
的组件,他是Info
的子组件,用来显示分数score
文本,
class CurrentScore extends StatelessWidget{
const CurrentScore({super.key});
@override
Widget build(BuildContext context){
//调用Info中的共享数据
final Info? info = Info.of(context);
return Container(
child: Text('$info?.score'),
);
}
}
- 完整代码
import 'dart:math';
import 'package:flutter/material.dart';
class InheritedWidgetPage extends StatefulWidget {
const InheritedWidgetPage({Key? key}) : super(key: key);
@override
State<InheritedWidgetPage> createState() => _InheritedWidgetPageState();
}
class _InheritedWidgetPageState extends State<InheritedWidgetPage> {
late int _score = 50;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('InheritedWidget'),),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Info(
score: _score,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Icon(Icons.score),
CurrentScore(),
],
)
),
OutlinedButton(
onPressed: (){
//点击改变分数
setState(() {
_score = Random().nextInt(100);
});
},
child: const Text('点击改变分数'),
)
],
),
),
);
}
}
class Info extends InheritedWidget {
final int score;//需要在子树中共享的数据
const Info({
Key? key,
required this.score,
required Widget child,
}) : super(key: key,child: child);
//创建Info方法从子树中的widget获取共享数据
static Info? of(BuildContext context){
return context.dependOnInheritedWidgetOfExactType<Info>();
}
//该回调决定当data发生变化时,是否通知子树中依赖data的Widget重新build
@override
bool updateShouldNotify(covariant Info oldWidget){
return score != oldWidget.score;
}
}
class CurrentScore extends StatelessWidget{
const CurrentScore({super.key});
@override
Widget build(BuildContext context){
//调用Info中的共享数据
final Info? info = Info.of(context);
return Container(
child: Text('${info?.score}'),
);
}
}
相当父组件传值给子组件,子组件接受并且显示。