Flutter fish redux入门

fish redux

本分主要介绍闲鱼出品的fish redux基础知识和使用,后续会有复杂应用场景分享。

flutter自带demo
void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(title: 'Flutter Demo Home Page'),
      debugShowCheckedModeBanner: false,
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('$_counter'),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

flutter的计数demo,方便后面对比。

redux

简介Redux的流程
redux流程

简单说就是用户操作dispatcher(action),到reducer中处理相关数据和逻辑,存储数据到store中,更新state,触发UI刷新。

fish redux

部分重要概念

  1. component
    对局部的展示和功能的封装。对功能细分为修改数据的功能(Reducer)和非修改数据的功能(副作用Effect)。于是有了View、Effect、Reducer组件三要素。
  2. action
  • Action 包含两个字段
    • type
    • payload
  • 推荐的写法是
    • 为一个组件|适配器创建一个 action.dart 文件,包含两个类
      • 为 type 字段起一个枚举类
      • 为 Action 的创建起一个 ActionCreator 类,这样利于约束 payload 的类型。
    • Effect 接受处理的 Action,以 on{Verb} 命名
    • Reducer 接受处理的 Action,以{verb} 命名
    • 示例代码
enum MessageAction {
    onShare,
    shared,
}

class MessageActionCreator {
    static Action onShare(Map<String, Object> payload) {
        return Action(MessageAction.onShare, payload: payload);
    }

    static Action shared() {
        return const Action(MessageAction.shared);
    }
}
  1. reducer
  • Reducer 是一个上下文无关的 pure function。它接收下面的参数
    • T state
    • Action action
  • 它主要包含三方面的信息
    • 接收一个“意图”, 做出数据修改
    • 如果要修改数据,需要创建一份新的拷贝,修改在拷贝上。
    • 如果数据修改了,它会自动触发 State 的层层数据的拷贝,再以扁平化方式通知组件刷新。
  • 示例代码
Reducer<String> buildMessageReducer() {
  return asReducer(<Object, Reducer<String>>{
    'shared': _shared,
  });
}

String _shared(String msg, Action action) {
  return '$msg [shared]';
}

class MessageComponent extends Component<String> {
    MessageComponent(): super(
            view: buildMessageView,
            effect: buildEffect(),
            reducer: buildMessageReducer(),
        );
}
  1. effect
    接收View的"意图",也包括对生命周期的回调。不修改数据,它对数据是只读的,如果要修改,应该发送一个Action到Reducer中去处理
cunter fish redux 版

基础目录
> -action.dart
> -effect.dart(本例中非必须)
> -page.dart
> -reducer.dart
> -state.dart
> -view.dart

action.dart

enum CounterAction { add, onAdd }

class CounterActionCreator {
  //reducer使用
  static Action add() {
    return const Action(CounterAction.add);
  }
  //effect使用
  static Action onAdd() {
    return const Action(CounterAction.onAdd);
  }
}

state.dart

class CounterState implements Cloneable<CounterState> {
  int count = 0;

  @override
  CounterState clone() {
    return CounterState()..count = count;
  }
}

CounterState initState(Map<String, dynamic> args){
  //什么也没做,只是初始化数据
  return CounterState();
}

reducer.dart

Reducer<CounterState> buildReducer() {
  return asReducer<CounterState>(<Object, Reducer<CounterState>>{
    CounterAction.add: _add,
  });
}

CounterState _add(CounterState state, Action action) {
  final CounterState newState = state.clone();
  newState.count = ++state.count;
  return newState;
}

effect.dart

Effect<CounterState> buildEffect() {
  return combineEffects(<Object, Effect<CounterState>>{
    CounterAction.onAdd: _onAdd,
  });
}

void _onAdd(Action action, Context<CounterState> ctx) {
  print("_onAdd");
  ctx.dispatch(CounterActionCreator.add());
}

view.dart

Widget buildView(
    CounterState state, Dispatch dispatch, ViewService viewService) {
  return Scaffold(
    appBar: AppBar(
      title: Text('CounterFishRedux'),
    ),
    body: Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text(
            state.count.toString(),
          )
        ],
      ),
    ),
    floatingActionButton: FloatingActionButton(
      //发送的action到了Effect中处理
      onPressed: () => dispatch(CounterActionCreator.onAdd()),
      //也可以发action到reducer中处理
      //onPressed: () => dispatch(CounterActionCreator.add()),
      tooltip: 'add',
      child: Icon(Icons.add),
    ),
  );
}

page.dart

class CounterFishReduxPage extends Page<CounterState, Map<String, dynamic>> {
  CounterFishReduxPage()
      : super(
          initState: initState,
          effect: buildEffect(),
          reducer: buildReducer(),
          view: buildView,
        );
}

​ 在view.dart中,用户触发FloatingActionButton的onPress事件,dispatch了名为onAdd的Action,在effect.dart中接收到action,会继续dispatch,到reducer.dart中(这一步非必须,可以直接dispatch到reducer.dart中),在reducer.dart中,在state中取出state中的数据,处理(加一)后,返回state,数据更新到store中,触发UI更新,最终到view.dart中state中的数据会更新,取出新的数据显示。

​ fish redux适用于中大型项目,这种简单的功能直接用官方的setState即可。

​ 这样就可以单独作为一个page或者component使用,没有逻辑和UI的耦合。

更多更新关注微信公众号“Flutter入门” 知乎专栏同名
Flutter入门

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值