阅读 84

Flutter实战之状态管理Redux篇

前言

采用开源库flutter_redux让Flutter应用具有状态管理能力并介绍如何使用flutter_redux。

Redux概要

可能你不需要Redux框架并非所有项目都需要它,事实上也确实如此。但作为状态管理框架对于开发复杂项目来说其作用可以很好管理项目状态。

State

state就是要管理的状态模型,通过state获取所需的状态数据以及更新和修改对应的状态数据。

Action

Redux中所有的更新动作就是通过action完成。通过Redux的dispatch通知到Reducer去更新Store树的state状态。

Reducer

combineReducers就是所谓Reducer,因为一个子State并不一定只接受一种action,combineReducers其实就是接受actions的集合。更新某一个State的状态所有actions都应该定义在该combineReducers中。

代码时间

Step1

定义全局State类,然后根据功能性不同再做拆分细分出不同状态管理的state。像例子中拆分出应用主题状态管理和语言状态管理。这里将Redux框架其他类都罗列在了一起:state、combineReducers、action。例如AppLocalState中localReducer定义了一个TypedReducer定义接受状态state类型和action方法。action是一个类,参数是传递更新AppLocalState的state。setLocal是状态处理方法接收action传递的state并做中间处理工作,处理结束后并返回对应state。

/************全局部分 Start***************/
/**
 * 应用全局状态
 */
class AppGlobalState{
  AppLocalState appLocalState;
  AppThemeState appThemeState;

  AppGlobalState({this.appLocalState, this.appThemeState});


}
/**
 * 应用全局Reducer入口用于定义子Reducer
 */
AppGlobalState globalReducer(AppGlobalState state,action){
  return AppGlobalState(
      appLocalState: localReducer(state.appLocalState,action),
      appThemeState: themeReducer(state.appThemeState,action)
  );
}
/************全局部分 End***************/

/************语言部分 Start***************/
/**
 * 应用语言状态类
 */

class AppLocalState {
  Locale locale;

  AppLocalState(this.locale);
}
/**
 * 全局语言reducer接收action
 */
final localReducer = combineReducers<AppLocalState>([
  TypedReducer<AppLocalState, setAppLocalAction>(setLocal),
]);

/**
 * setAppLocalAction接受处理方法
 */
AppLocalState setLocal(AppLocalState appLocalState, action) {
  appLocalState = action.appLocalState;
  return appLocalState;
}

/**
 * 设置应用语言action
 */
class setAppLocalAction {
  final AppLocalState appLocalState;

  setAppLocalAction(this.appLocalState);
}
/************语言部分 End***************/

/************主题部分 Start***************/

/**
 * 应用主题状态类
 */
class AppThemeState {
  ThemeData themeData;

  AppThemeState(this.themeData);
}
/**
 * 设置应用主题Action
 */
class setAppThemeAction {
  final AppThemeState appThemeState;
  setAppThemeAction(this.appThemeState);
}

/**
 * setAppThemeAction接受处理方法
 */
AppThemeState setAppTheme(AppThemeState appThemeState, action) {
  appThemeState = action.appThemeState;
  return appThemeState;
}
/**
 * 全局主题Reducer接受action
 */
final themeReducer = combineReducers<AppThemeState>([
  TypedReducer<AppThemeState, setAppThemeAction>(setAppTheme),
]);

 /************主题部分 End***************/
复制代码

Step2

接着在Widget中接入Redux框架,首先初始化全局Store对象。预先设置初始化的AppGlobalState对象,设置全局reducer入口。最后使用StoreProvider作为根布局的Widget节点,然后在包含MaterialApp。虽然对于这种方式总觉得奇怪以及后期修改层级确实看着比较麻烦,但对于Flutter层层嵌套的特性应该也习以为常了吧。

  //初始化Store
  final store = Store<AppGlobalState>(globalReducer,
      initialState: AppGlobalState(
        appLocalState: AppLocalState(Locale("zh")),
        appThemeState: AppThemeState(ThemeData(primaryColor: Colors.blue)),
      ));
 @override
  Widget build(BuildContext context) {
    return StoreProvider(
      store: store,
      child: StoreBuilder<AppGlobalState>(
        builder: (context, store) {
            return MaterialApp(...)
        },
      ),
    );
  }
复制代码

Step3

最后是对状态更新操作,调用StoreProvider的dispatch方法,设置需要更新action操作就可以实现对state的更新。

Tips:需要注意的是context上下文必须是StoreBuilder中的context,若使用的是Widget Builder的context则会报错。

StoreProvider.of<AppGlobalState>(context).dispatch(setAppThemeAction(
    AppThemeState(ThemeData(primaryColor: themeColor = Colors.blue))));
StoreProvider.of<AppGlobalState>(context)
    .dispatch(setAppLocalAction(AppLocalState(Locale("en"))));
复制代码

Step4

store的获取方式就是在组件中嵌套StoreBuilder获取store。只要是需要使用到store的地方都需要嵌套一层StoreWidget,但从全局状态管理上来看已经大大减少了开发成本。

class AppLocalization extends StatefulWidget {
  final Widget child;

  AppLocalization({this.child});

  @override
  _AppLocalizationState createState() => _AppLocalizationState();
}

class _AppLocalizationState extends State<AppLocalization> {
  @override
  Widget build(BuildContext context) {
    return StoreBuilder<AppGlobalState>(
      builder: (context, store) {
        return Localizations.override(
          context: context,
          locale: store.state.appLocalState.locale,
          child: widget.child,
        );
      },
    );
  }
}
复制代码
关注下面的标签,发现更多相似文章
评论