新闻资讯
fish_redux 实现全局状态
fish_redux全局状态的实现,我们参考 官方 demo,首先构造一个GlobalBaseState抽象类(涉及到全局状态变化的state都需要继承该类),这个类定义了全局变化的状态属性,例如我们该例中需要实现全局的主题色,语言和字体的改变,那么我们就可以如下定义
abstract class GlobalBaseState {
Color get themeColor; set themeColor(Color color);
Locale get localization; set localization(Locale locale); String get fontFamily; set fontFamily(String fontFamily);
}
接着需要定义一个全局State,继承自GlobalBaseState并实现Cloneable
class GlobalState implements GlobalBaseState, Cloneable<GlobalState> { @override Color themeColor; @override Locale localization; @override String fontFamily; @override GlobalState clone() { return GlobalState()
..fontFamily = fontFamily
..localization = localization
..themeColor = themeColor;
}
}
接着需要定义一个全局的store来存储状态值
class GlobalStore { // Store 用来存储全局状态 GlobalState,当刷新状态值的时候,通过 // store 的 dispatch 发送相关的 action 即可做出相应的调整 static Store<GlobalState> _globalStore; static Store<GlobalState> get store => _globalStore ??= createStore(
GlobalState(),
buildReducer(), // reducer 用来刷新状态值 );
} /// action enum GlobalAction { changeThemeColor, changeLocale, changeFontFamily } class GlobalActionCreator { static Action onChangeThemeColor(Color themeColor) { return Action(GlobalAction.changeThemeColor, payload: themeColor);
} static Action onChangeLocale(Locale localization) { return Action(GlobalAction.changeLocale, payload: localization);
} static Action onChangeFontFamily(String fontFamily) { return Action(GlobalAction.changeFontFamily, payload: fontFamily);
}
} /// reducer 的作用就是刷新主题色,字体和语言 Reducer<GlobalState> buildReducer() { return asReducer(<Object, Reducer<GlobalState>>{
GlobalAction.changeThemeColor: _onThemeChange,
GlobalAction.changeLocale: _onLocalChange,
GlobalAction.changeFontFamily: _onFontFamilyChange,
});
}
GlobalState _onThemeChange(GlobalState state, Action action) { return state.clone()..themeColor = action.payload;
}
GlobalState _onLocalChange(GlobalState state, Action action) { return state.clone()..localization = action.payload;
}
GlobalState _onFontFamilyChange(GlobalState state, Action action) { return state.clone()..fontFamily = action.payload;
}
定义完全局State和Store后,回到我们的main.dart下注册路由部分,一开始我们使用PageRoutes的时候只传入了page参数,还有个visitor参数没有使用,这个就是用来刷新全局状态的。
final AbstractRoutes routes = PageRoutes(
pages: <String, Page<Object, dynamic>>{ // ... },
visitor: (String path, Page<Object, dynamic> page) { if (page.isTypeof<GlobalBaseState>()) { // connectExtraStore 方法将 page store 和 app store 连接起来 // globalUpdate() 就是具体的实现逻辑 page.connectExtraStore<GlobalState>(GlobalStore.store, globalUpdate());
}
}); /// globalUpdate globalUpdate() => (Object pageState, GlobalState appState) { final GlobalBaseState p = pageState; if (pageState is Cloneable) { final Object copy = pageState.clone(); final GlobalBaseState newState = copy; // pageState 属性和 appState 属性不相同,则把 appState 对应的属性赋值给 newState if (p.themeColor != appState.themeColor) {
newState.themeColor = appState.themeColor;
} if (p.localization != appState.localization) {
newState.localization = appState.localization;
} if (p.fontFamily != appState.fontFamily) {
newState.fontFamily = appState.fontFamily;
} return newState; // 返回新的 state 并将数据设置到 ui } return pageState;
};
定义好全局State和Store之后,只需要PageState继承GlobalBaseState就可以愉快的全局状态更新了,例如我们查看ui/settings该界面涉及了全局状态的修改,state,action等可自行查看,我们直接看view
Widget buildView(SettingsState state, Dispatch dispatch, ViewService viewService) { return Theme(
data: ThemeData(primarySwatch: state.themeColor),
child: Scaffold(
appBar: AppBar(
title: Text(
FlutterI18n.translate(_ctx, I18nKeys.settings),
style: TextStyle(fontSize: SpValues.titleTextSize, fontFamily: state.fontFamily),
),
),
body: ListView(
children: <Widget>[
ExpansionTile(
leading: Icon(Icons.color_lens),
title: Text(
FlutterI18n.translate(_ctx, I18nKeys.themeColor),
style: TextStyle(fontSize: SpValues.settingTextSize, fontFamily: state.fontFamily),
),
children: List.generate(ResourceConfigs.themeColors.length, (index) { return GestureDetector(
onTap: () { // 发送对应的修改主题色的 action,effect 根据 action 做出相应的响应策略 dispatch(SettingsActionCreator.onChangeThemeColor(index));
},
child: Container(
margin: EdgeInsets.fromLTRB(8.0, 4.0, 8.0, 4.0),
width: _size.width,
height: _itemHeight,
color: ResourceConfigs.themeColors[index],
),
);
}),
), // 省略语言选择,字体选择,逻辑同主题色选择,具体查看 `setting/view.dart` 文件 ],
),
),
);
} /// effect Effect<SettingsState> buildEffect() { return combineEffects(<Object, Effect<SettingsState>>{
SettingsAction.changeThemeColor: _onChangeThemeColor,
});
} void _onChangeThemeColor(Action action, Context<SettingsState> ctx) { // 通过 GlobalStore dispatch 全局变化的 action,全局的 reducer 做出响应,并修改主题色 GlobalStore.store.dispatch(GlobalActionCreator.onChangeThemeColor(ResourceConfigs.themeColors[action.payload]));
}
别的界面也需要做类似的处理,就可以实现全局切换状态啦~
原文链接:https://juejin.im/post/5e4f5bbce51d4526c550a7fe
回复列表