新闻资讯

新闻资讯 行业动态

fish_redux 实现全局状态

编辑:008     时间:2020-02-25

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
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

回复列表

相关推荐