Flutter之InheritedWidget的妙用
在看文章前,先想下这几个问题:
- 问题1. 在一个widget中如何让子widget也得到这个widget的属性呢?比如MaterialApp中theme主题属性,如何让子widget也可以得到使用theme呢?
- 问题2 . InheritedWidget该如何使用呢?注意什么?跟状态管理有什么不同?
InheritedWidget的理解
从Inherited字面可以得知它是继承的一个widget,那什么是继承呢?学过面向对象都知道,如果一个父类对象有的属性,通过继承子类对象也有这个属性。那在flutter中也是差不多的,由于flutter基本上都是一层套一层的创建对象传递参数,想要让子类持有父类的属性变量变得有点难处理,于是InheritedWidget出来就来解决这个问题了。
说了这么多,就是一句话:可以有效的将数据在当前Widget中的子Widget中传递下去。
创建
- 写个类继承InheritedWidget,重写updateShouldNotify
- 写要存储的变量以及对应的构造方法
class ShareWidget extends InheritedWidget{
//存储的变量
final int data;//可以是类,可以简单类型
///构造函数
const ShareWidget({Key key,@required this.data,@required Widget child}) : super(key: key,child: child);
///framework通过使用旧widget占据树中的这个位置的小部件作为参数调用这个函数来区分这些情况。
@override
bool updateShouldNotify(ShareWidget oldWidget) {
return oldWidget.data != data;//一般比较的是数据是不是不一样
}
}
使用
使用的使用一定在需要获取属性的widget最顶部使用,这样子widget才能获取到,绝对不能是兄弟关系,
获取
//定义一个方法,方便子树中的widget获取这个widget,进而获得共享数据。
static ShareWidget of(BuildContext context){
/**
* 获取最近的给定类型的Widget,该widget必须是InheritedWidget的子类,
* 并向该widget注册传入的context,当该widget改变时,
* 这个context会重新构建以便从该widget获得新的值。
* 这就是child向InheritedWidget注册的方法。
*/
return context.inheritFromWidgetOfExactType(ShareWidget);
}
状态数据
我项目中使用provider,可以看下provider的源码核心也是使用这个类来达到数据共享的,
可以看到InheritedProvider也是继承的InheritedWidget,更为高级的是使用了泛型,这样的好处可以支持的类型更多了,兼容性和扩展性更强。