flutter中redux使用

309 阅读2分钟

他其实是状态管理:App内有多个地方使用到登陆用户的数据,这时候如果某处对用户数据做了修改,各个页面的同步更新会是一件麻烦的事情。但是引入 Redux 后,某个页面修改了当前用户信息,所有绑定了 Redux 的控件,将由 Redux 自动同步刷新。

一般用法如下,比如我要保存一个用户信息UserInfo。

第一步我们需要创建一个State类,这里保存着需要全局的对象。状态是由reducer生成并储存在Store里面的。Store更新状态的时候,并不是更改原来的状态对象,而是直接将reducer生成的新的状态对象替换掉老的状态对象。

class UserInfoState {
  UserInfo userInfo;
  UserInfoState(this.userInfo);
}

第二步创建action。这个action其实就是对状态进行操作的方法的一个代号

class UpdateUserInfoAction {
  final UserInfo userInfo;
  UpdateUserInfoAction(this.userInfo);
}

第三步创建reducer。这个reducer这里一共有两个,一个是创建Store时需要的,一个则是生成新的状态的reducer

UserInfoState appReducer(UserInfoState userInfoState,  action) {
  return UserInfoState(UserInfoReducer(userInfoState.userInfo, action));
}

final UserInfoReducer = combineReducers<UserInfo>([
  TypedReducer<UserInfo, UpdateUserInfoAction>(_updateUser),
]);

UserInfo _updateUser(UserInfo info, UpdateUserInfoAction action) {
  info = action.userInfo;
  return info;
}

userInfo如下

class UserInfo {
  String name;
  int id;

  UserInfo(this.name, this.id);

  UserInfo.empty();
}

到此准备工作已经做好了。

第四步要在APP的顶层创建这个store(runApp前或者MyApp(store))

void main() {
  final store = Store<UserInfoState>(appReducer,
      initialState: new UserInfoState(UserInfo.empty()));
  runApp(MyApp(store));
}

而且在MyApp中build时,其根节点为StoreProvider

class MyApp extends StatelessWidget {
  final Store<UserInfoState> store;

  MyApp(this.store);

  @override
  Widget build(BuildContext context) {
    return StoreProvider(
      store: store,
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: TopScreen(),
      ),
    );
  }
}

第五步则是在子页面中使用或者更新这个State,我们通常使用StoreConnector,因为只要State更新,他就会rebuild,比如这里的top_screen 首先看看需要刷新的使用

class TopScreen extends StatefulWidget {
  @override
  _TopScreenState createState() => _TopScreenState();
}

class _TopScreenState extends State<TopScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Top Screen'),
      ),
      body: Center(
        child: StoreConnector<UserInfoState,UserInfo>(
          converter: (store) => store.state.userInfo,
          builder: (context, userInfo) { 
            return Text(
              userInfo.id.toString(),
              style: Theme.of(context).textTheme.display1,
            );
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context){
            return MyHomePage();
          }));
        },
        child: Icon(Icons.forward),
      ),
    );
  }
}

可以看到我们在构建的时候,将Widget的生成放到StoreConnector的builder中,如果在其他页面更改了UserInfo,那么这里会实时的更改。至于发送更新的action,我们也可以按照上面的方式,也可以直接用 store.dispatch(action);store的获取store = StoreProvider.of(context);该段代码应该放在stateClass中获取,比如这里是在 didChangeDependencies()方法中获取的。然后在build中直接发送action。如果还是放在StoreConnector中则如下

floatingActionButton: StoreConnector<CountState,VoidCallback>(
  converter: (store) {
    return () => store.dispatch(Action.increment);
  },
  builder: (context, callback) {
    return FloatingActionButton(
      onPressed: callback,
      child: Icon(Icons.add),
    );
  },
),