在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}'),
);
}
}
相当父组件传值给子组件,子组件接受并且显示。
