W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
應(yīng)用程序中通常會(huì)包含一些貫穿 APP 生命周期的變量信息,這些信息在 APP 大多數(shù)地方可能都會(huì)被用到,比如當(dāng)前用戶信息、Local 信息等。在 Flutter 中我們把需要全局共享的信息分為兩類:全局變量和共享狀態(tài)。全局變量就是單純指會(huì)貫穿整個(gè) APP 生命周期的變量,用于單純的保存一些信息,或者封裝一些全局工具和方法的對(duì)象。而共享狀態(tài)則是指哪些需要跨組件或跨路由共享的信息,這些信息通常也是全局變量,而共享狀態(tài)和全局變量的不同在于前者發(fā)生改變時(shí)需要通知所有使用該狀態(tài)的組件,而后者不需要。為此,我們將全局變量和共享狀態(tài)分開單獨(dú)管理。
我們?cè)凇發(fā)ib/common”目錄下創(chuàng)建一個(gè)Global
類,它主要管理 APP 的全局變量,定義如下:
// 提供五套可選主題色
const _themes = <MaterialColor>[
Colors.blue,
Colors.cyan,
Colors.teal,
Colors.green,
Colors.red,
];
class Global {
static SharedPreferences _prefs;
static Profile profile = Profile();
// 網(wǎng)絡(luò)緩存對(duì)象
static NetCache netCache = NetCache();
// 可選的主題列表
static List<MaterialColor> get themes => _themes;
// 是否為release版
static bool get isRelease => bool.fromEnvironment("dart.vm.product");
//初始化全局信息,會(huì)在APP啟動(dòng)時(shí)執(zhí)行
static Future init() async {
_prefs = await SharedPreferences.getInstance();
var _profile = _prefs.getString("profile");
if (_profile != null) {
try {
profile = Profile.fromJson(jsonDecode(_profile));
} catch (e) {
print(e);
}
}
// 如果沒有緩存策略,設(shè)置默認(rèn)緩存策略
profile.cache = profile.cache ?? CacheConfig()
..enable = true
..maxAge = 3600
..maxCount = 100;
//初始化網(wǎng)絡(luò)請(qǐng)求相關(guān)配置
Git.init();
}
// 持久化Profile信息
static saveProfile() =>
_prefs.setString("profile", jsonEncode(profile.toJson()));
}
Global 類的各個(gè)字段的意義都有注釋,在此不再贅述,需要注意的是init()
需要在 App 啟動(dòng)時(shí)就要執(zhí)行,所以應(yīng)用的main
方法如下:
void main() => Global.init().then((e) => runApp(MyApp()));
在此,一定要確保Global.init()
方法不能拋出異常,否則 runApp(MyApp())
根本執(zhí)行不到。
有了全局變量,我們還需要考慮如何跨組件共享狀態(tài)。當(dāng)然,如果我們將要共享的狀態(tài)全部用全局變量替代也是可以的,但是這在 Flutter 開發(fā)中并不是一個(gè)好主意,因?yàn)榻M件的狀態(tài)是和 UI 相關(guān),而在狀態(tài)改變時(shí)我們會(huì)期望依賴該狀態(tài)的 UI 組件會(huì)自動(dòng)更新,如果使用全局變量,那么我們必須得去手動(dòng)處理狀態(tài)變動(dòng)通知、接收機(jī)制以及變量和組件依賴關(guān)系。因此,本實(shí)例中,我們使用前面介紹過的 Provider 包來實(shí)現(xiàn)跨組件狀態(tài)共享,因此我們需要定義相關(guān)的 Provider。在本實(shí)例中,需要共享的狀態(tài)有登錄用戶信息、APP 主題信息、APP 語(yǔ)言信息。由于這些信息改變后都要立即通知其它依賴的該信息的 Widget 更新,所以我們應(yīng)該使用ChangeNotifierProvider
,另外,這些信息改變后都是需要更新 Profile 信息并進(jìn)行持久化的。綜上所述,我們可以定義一個(gè)ProfileChangeNotifier
基類,然后讓需要共享的 Model 繼承自該類即可,ProfileChangeNotifier
定義如下:
class ProfileChangeNotifier extends ChangeNotifier {
Profile get _profile => Global.profile;
@override
void notifyListeners() {
Global.saveProfile(); //保存Profile變更
super.notifyListeners(); //通知依賴的Widget更新
}
}
用戶狀態(tài)在登錄狀態(tài)發(fā)生變化時(shí)更新、通知其依賴項(xiàng),我們定義如下:
class UserModel extends ProfileChangeNotifier {
User get user => _profile.user;
// APP是否登錄(如果有用戶信息,則證明登錄過)
bool get isLogin => user != null;
//用戶信息發(fā)生變化,更新用戶信息并通知依賴它的子孫Widgets更新
set user(User user) {
if (user?.login != _profile.user?.login) {
_profile.lastLogin = _profile.user?.login;
_profile.user = user;
notifyListeners();
}
}
}
主題狀態(tài)在用戶更換 APP 主題時(shí)更新、通知其依賴項(xiàng),定義如下:
class ThemeModel extends ProfileChangeNotifier {
// 獲取當(dāng)前主題,如果為設(shè)置主題,則默認(rèn)使用藍(lán)色主題
ColorSwatch get theme => Global.themes
.firstWhere((e) => e.value == _profile.theme, orElse: () => Colors.blue);
// 主題改變后,通知其依賴項(xiàng),新主題會(huì)立即生效
set theme(ColorSwatch color) {
if (color != theme) {
_profile.theme = color[500].value;
notifyListeners();
}
}
}
當(dāng) APP 語(yǔ)言選為跟隨系統(tǒng)(Auto)時(shí),在系通語(yǔ)言改變時(shí),APP 語(yǔ)言會(huì)更新;當(dāng)用戶在 APP 中選定了具體語(yǔ)言時(shí)(美國(guó)英語(yǔ)或中文簡(jiǎn)體),則 APP 便會(huì)一直使用用戶選定的語(yǔ)言,不會(huì)再隨系統(tǒng)語(yǔ)言而變。語(yǔ)言狀態(tài)類定義如下:
class LocaleModel extends ProfileChangeNotifier {
// 獲取當(dāng)前用戶的APP語(yǔ)言配置Locale類,如果為null,則語(yǔ)言跟隨系統(tǒng)語(yǔ)言
Locale getLocale() {
if (_profile.locale == null) return null;
var t = _profile.locale.split("_");
return Locale(t[0], t[1]);
}
// 獲取當(dāng)前Locale的字符串表示
String get locale => _profile.locale;
// 用戶改變APP語(yǔ)言后,通知依賴項(xiàng)更新,新語(yǔ)言會(huì)立即生效
set locale(String locale) {
if (locale != _profile.locale) {
_profile.locale = locale;
notifyListeners();
}
}
}
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: