最近在研究使用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);
}
}