flutter
中我们可能会存在这样一个需求,我有一个公共信息需要保存,同时应用到整个项目或者是一个页面,flutter
就提供了这个一个组件 InheritedWidget
,同时其也是 provider
框架的基础,下面就简单介绍一下
provider地址:这里不介绍,下篇文章介绍
demo地址(inherited文件夹):里面也有 provider 的案例
InheritedWidget
InheritedWidget
在我们身边非常常见,例如: pull_to_refresh
、provider
等,可以在我们的 MaterialApp
外侧包裹一个组件,里面就用到了InheritedWidget
,这个就是全局共享信息用的,且共享信息更新的话,使用了公共信息的组件也会自动更新内容
话不多说了,先创建一个 InheritedWidget 子类
创建完成之后我们完善一下,默认构造方法
、of
、updateShouldNotify
方法
of
方法就和 Navigator.of
一样,可以用来通过类名 + of
获取实例
updateShouldNotify
用于根据内部属性判断是否需要通知外部更新,触发更新时会响应外部组件的 didChangeDependencies
方法,可以用来做一些事请
//继承自 ProxyWidget、Widget 无状态,如果有状态外面套一个 StatefulWidget就可以动态动态修改内容了😂
//假设我们仅仅用于个人页面
class MyInheritedWidget extends InheritedWidget {
//用来保存我们的对象,要标记为 final,里面不能直接修改,可以通过修改外面传递的值来修改该内容触发更新
final String username;
const MyInheritedWidget({
Key? key,
required this.username,
required Widget child,
}) : super(key: key, child: child);
//就像 Navigator.of(context)一样获取,用于调用内部参数
static MyInheritedWidget of(BuildContext context) {
final MyInheritedWidget? result = context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>();
assert(result != null, 'No MyInherited found in context');
return result!;
}
//更新时用于判断、过滤是否通知外部更新
//如果外部使用的是 StatefulWidget,变更时会调用didChangeDependencies,以此来通知对应页面进行其他调整
@override
bool updateShouldNotify(MyInheritedWidget oldWidget) {
//返回为true就是通知更新,否则不更新
//这里我们过滤一下,如果值没发生改变,我们就不通知外面即可
return username != oldWidget.username;
}
}
下面我们试用一下自己封装的,同时应用到一个 StatefulWidget
和 StatelessWidget
,都完全ok,里面也都能够接收到内容的变更
同时通过案例也可以看到,使用局限性也挺大的,需要通过更新外部传入值,从而更新其他所有页面内容,当跨页面太多时,就不好用了,因此比较适用于静态数据
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
//作为传入 InheritedWidget 的参数,更改其来通知其他页面更新
String userName = '默认userName';
@override
void didChangeDependencies() {
super.didChangeDependencies();
print("didChangeDependencies");
}
@override
Widget build(BuildContext context) {
//就像这样一样,外面嵌套一个 StatefulWidget 就可以随便修改 InheritedWidget 属性,从而触发属性更新,再应用到指定地方
return MyInheritedWidget(
username: userName, //通过外面修改该参数,间接修改里面内容
child: Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
const TestWidget(),
const TestFullWidget(),
IconButton(
onPressed: () {
setState(() {
userName = '分享了';
});
},
icon: const Icon(
Icons.share,
color: Colors.green,
),
),
IconButton(
onPressed: () {
setState(() {
userName = '邮件了';
});
},
icon: const Icon(
Icons.mail,
color: Colors.green,
),
),
],
),
),
),
);
}
}
class TestWidget extends StatelessWidget {
const TestWidget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Text(MyInheritedWidget.of(context).username, textAlign: TextAlign.center,);
}
}
class TestFullWidget extends StatefulWidget {
const TestFullWidget({Key? key}) : super(key: key);
@override
State<TestFullWidget> createState() => _TestFullWidgetState();
}
class _TestFullWidgetState extends State<TestFullWidget> {
@override
void initState() {
super.initState();
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
}
@override
Widget build(BuildContext context) {
return Text(MyInheritedWidget.of(context).username, textAlign: TextAlign.center);
}
}
最后
通过上面使用和案例,可以看出来,若其只用静态数据展示,还是非常优秀的,例如:一些全局数据等,一些三方的全局信息(一些三方自己也这么用)
如果需要多个页面有联动更新,那么这个就不是那么好使用了,还需要改进才行,下一章的 provider 将会完美解决这个问题