最近在研究使用Flutter来写一个跨平台的App,之前研究过使用Java来编写Android应用,且对于Java语言也比较熟悉,而Flutter使用Dart语言来编写的,因此在熟悉Dart语言和Flutter框架的过程中也遇到不少问题。
看了很多网上的资料和官方文档,Dart似乎不支持全局变量,而且Flutter将所有的东西抽象为Widget,并将其分为有状态的StatefulWidget和无状态的StatelessWidget,每一个控件中的变量都被抽象成了状态state,有状态的state改变的时候就会刷新控件达到改变的目的,因此问题就转化为了如何定义一个多个控件共享的state,比如Flutter提供的InheritedWidget就可以实现类似全局变量的功能。
一、InheritedWidget
InheritedWidget是一个小部件的基类,用于有效地Widget树中传播信息,InheritedWidget的子控件会自动搜寻其祖先节点中离自己最近的InheritedWidget控件,并获取InheritedWidget控件的变量,因此全局变量只需要定义在InheritedWidget中,并用InheritedWidget控件作为需要共享该变量的祖先节点就可以了。
下面看一下官方提供的例子:
class FrogColor extends InheritedWidget {
const FrogColor({
Key key,
@required this.color,
@required Widget child,
}) : assert(color != null),
assert(child != null),
super(key: key, child: child);
final Color color;
static FrogColor of(BuildContext context) {
return context.inheritFromWidgetOfExactType(FrogColor) as FrogColor;
}
@override
bool updateShouldNotify(FrogColor old) => color != old.color;
}
其中,Color就是共享的变量;
of方法是一个静态方法,该方法调用BuildContext.inheritFromWidgetOfExactType,用来返回FrogColor部件,当然也可以返回数据,比如保存的共享变量Color;
updateShouldNotify方法是该控件的刷新逻辑,上面的方法体中就表示当color的值改变的时候刷新控件。
二、共享可变变量
用官方提供的例子由于是用final修饰的,因此子控件不能够改变其值,如果想要创建一个可变得变量,就可以用到我们一开始提到的state,在InheritedWidget中保存一个StatefulWidget,就可以通过这个StatefulWidget来管理要保存的变量了:
class _SharedInherited extends InheritedWidget {
_SharedInherited({
Key key,
@required Widget child,
@required this.data,
}) : super(key: key, child: child);
final SharedInheritedWidgetState data; //通过一个StatefulWidgetState来保存数据
@override
bool updateShouldNotify(_SharedInherited oldWidget) { //数据更新
return data != oldWidget.data;
}
}
class SharedInheritedWidget extends StatefulWidget {
SharedInheritedWidget({
Key key,
this.child,
}) : super(key: key);
final Widget child;
@override
SharedInheritedWidgetState createState() =>
new SharedInheritedWidgetState();
static SharedInheritedWidgetState of(BuildContext context) {
return (context.inheritFromWidgetOfExactType(_SharedInherited)
as _SharedInherited)
.data;
}
}
class SharedInheritedWidgetState extends State<SharedInheritedWidget> {
String _sharedVal = ''; //共享变量
void setSharedVal(String newVal) {
setState(() {
_sharedVal = newVal;
});
}
String getSharedVal() {
return _sharedVal;
}
@override
Widget build(BuildContext context) {
return _SharedInherited(child: widget.child, data: this);
}
}