美文网首页
Flutter | 状态管理探索篇 Redux

Flutter | 状态管理探索篇 Redux

作者: sirai | 来源:发表于2019-06-13 11:18 被阅读0次

Redux是一种单向数据流架构,可以轻松开发,维护和测试应用程序。

image.png
  • 我们在Redux中,所有的状态都储存在Store里。这个Store会放在App顶层。
  • View拿到Store储存的状态(State)并把它映射成视图。View还会与用户进行交互,用户点击按钮滑动屏幕等等,这时会因为交互需要数据发生改变。
  • Redux让我们不能让View直接操作数据,而是通过发起一个action来告诉* Reducer,状态得改变啦。
  • 这时候Reducer接收到了这个action,他就回去遍历action表,然后找到那个匹配的action,根据action生成新的状态并把新的状态放到Store中。
  • Store丢弃了老的状态对象,储存了新的状态对象后,就通知所有使用到了这个状态的View更新(类似setState)。这样我们就能够同步不同view中的状态了。

Lets go

这里我们以一个最简单的CountApp举例。简单介绍flutter_redux/redux的用法。该项目完整代码已上传Github

这是一个在不同页面使用Redux共享状态信息的app。这两个页面都依赖于一个数字,这个数字会随着我们按下按钮的次数而增加。


image.png

第一步:添加依赖

image.png

我们这里使用了redux/flutter_redux库,它们都是由Brian Egan大神编写的。其中flutter_redux是用来简化redux的使用的。

第二步:创建State

我们刚才介绍了Redux的流程,状态是由reducer生成并储存在Store里面的。Store更新状态的时候,并不是更改原来的状态对象,而是直接将reducer生成的新的状态对象替换掉老的状态对象。所以,我们的状态应该是immutable的。

import 'package:meta/meta.dart';
/**
 * State中所有属性都应该是只读的
 */
@immutable
class CountState{
  int _count;
  get count => _count;

  CountState(this._count);
}

第三步:创建action

可能各位最开始接触的时候对Action还会摸不着头脑。action到底是什么?View如何发出action。其实,action只是我们对状态进行操作方法的一个代号而已。在我们这个应用中,唯一的一个功能就是让count的值+1,所以我们这里只有一个action。

/**
 * 定义操作该State的全部Action
 * 这里只有增加count一个动作
 */
enum Action{
  increment
}

第四步:创建reducer

reducer是我们的状态生成器,它接收一个我们原来的状态,然后接收一个action,再匹配这个action生成一个新的状态。

/**
 * reducer会根据传进来的action生成新的CountState
 */
CountState reducer(CountState state,action){
  //匹配Action
    if(action == Action.increment){
      return CountState(state.count+1);
    }
    return state;
}

第五步:创建store

Store接收一个reducer,以及初始化State,我们想用Redux管理全局的状态的话,需要将store储存在应用的入口才行。而在应用打开时要先初始化一次应用的状态。所以在State中添加一个初始化的函数。

//这段代码写在State中
CountState.initState(){ _count = 0;}

//应用顶层
void main() {
  final store =
      Store<CountState>(reducer, initialState: CountState.initState());
  runApp(new MyApp(store));
}

第六步:将Store放入顶层

flutter_redux提供了一个很棒的widget叫做StoreProvider,它的用法也很简单,接收一个store,和child Widget。

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

  MyApp(this.store);

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

第六步:在子页面中获取Store中的state

这里建议大家把实际代码对照下面的解释一起看。

StoreConnector<CountState,int>(
              converter: (store) => store.state.count,
              builder: (context, count) {
                return Text(
                  count.toString(),
                  style: Theme.of(context).textTheme.display1,
                );
              },
            ),

要想获取store我们需要使用StoreConnector<S,ViewModel>。StoreConnector能够通过StoreProvider找到顶层的store。而且能够在state发生变化时rebuilt Widget

image.png
  • 首先这里需要强制声明类型,S代表我们需要从store中获取什么类型的state,ViewModel指的是我们使用这个State时的实际类型。
  • 然后我们需要声明一个converter<S,ViewModel>,它的作用是将Store转化成实际ViewModel将要使用的信息,比如我们这里实际上要使用的是count,所以这里将count提取出来。
  • builder是我们实际根据state创建Widget的地方,它接收一个上下文context,以及刚才我们转化出来的ViewModel,所以我们就只需要把拿到的count放进Text Widget中进行渲染就好了。

第七步:发出action

我们这个应用在第二个页面中,通过点击floatingActionButton发出了action,并通知reducer生成了新的状态。

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

  • 同样,我们还是使用StoreConnector<S,ViewModel>。这里由于是发出了一个动作,所以是VoidCallback。
  • store.dispatch发起一个action,任何中间件都会拦截该操作,在运行中间件后,操作将被发送到给定的reducer生成新的状态,并更新状态树。

以上便是在flutter中使用redux共享状态信息的全部内容。

相关文章

网友评论

      本文标题:Flutter | 状态管理探索篇 Redux

      本文链接:https://www.haomeiwen.com/subject/pinlfctx.html