前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >「 flutter 必知必会 」最强数据管理方案 flutter_redux 使用解析

「 flutter 必知必会 」最强数据管理方案 flutter_redux 使用解析

作者头像
圆号本昊
发布2021-12-30 16:31:52
9280
发布2021-12-30 16:31:52
举报
文章被收录于专栏:github@hornhuanggithub@hornhuang

一、前言

  • 上篇文章我们讨论了 InheritedWidget 的使用,但是当 widget 数量很多时,使用起来会越来越麻烦,所以本文再给大家分享下,flutter_redux 的使用方法

flutter_redux是基于InheritedWidget封装的用于Widget树的数据传递与共享的的一套框架,它能高效的完成数据共享,进而达到ui及时更新等目的,使用起来略显复杂,一般不是很多的数据更新不建议使用,直接用InheritedWidget就能解决,当Widget绑定的很多的时候,使用起来就会很爽了。

二、原理

  • redux 数据管理方式来自 reactReact的数据单向流通的,很多时候需要共享数据的时候就比较麻烦,需要不断地变量提升,也就导致数据上溯会非常的混乱。解决办法之一就是redux , 进行全局统一的数据管理,并且通过State 的更新驱动虚拟dom 更新,再经过diff算法结果驱动真实dom 的更新。优势是数据的结构清晰,各个组件之间的数据共享。
  • 由于原理内容比较复杂,而且这篇文章主要讲解使用,所以有关院里的详细内容可以查看 flutter_redux(redux状态管理源码详解)原理详解

三、使用

  • 我将 flutter_redux 的使用拆解为个步骤,他们分别是: 1.封装需要共享的数据 2.封装需要发送的消息(同时也有区分动作的作用) 3.数据修改与分发 4.声明 store 5.接受与更新 6.触发
  • 为了方便大家理解,这里我采用点击计数的例子为大家讲解具体过程
3.1 封装需要共享的数据
  • 我们将所需要共享、更新的数据封装成一个类
  • 首先新建文件 app_state.dart (这里我是对整个 app 共享所以叫这个名字,大家使用时对于修改命名就行)
  • 在这个类离封装需要的数据,由于这个例子是计数,所以用的是 count
代码语言:javascript
复制
class AppState {
  int count;

  AppState({
    this.count,
  });

  static AppState initialState() {
    return AppState(
      count: 0,
    );
  }

  AppState copyWith({count}) {
    return AppState(
      count: count ?? this.count,
    );
  }
}
  • 同时为了方便调用者使用,我们提供初始化方法:initialState 以及复制方法 copyWith
3.2 封装需要发送的消息
  • 这一步的主要作用是匹配,或者说是分发数据
  • 就是说:由于操作可能是多样的,比如有增加计数,也可能有减少,所以取药有一个对象来匹配操作
  • 所以最简单的做法是采用枚举 enum
  • 但采用枚举有一个劣势,比如用户点击后,可能是增加1,也可能增加10,还有更多可能这时就要给每种情况都增加一个枚举。以及更多附加逻辑
  • 为了解决这个问题,我们可以采用类来代替枚举,吧每一类型的操作抽象成一个类,后续再区分操作类型时采用 action.runtimeType 即可
  • 比如,针对我们点击增加数值,我们可以:
代码语言:javascript
复制
class IncrementAction {
  final payload;

  IncrementAction({this.payload});
}
3.4 数据修改与分发
  • 根据 3.2 中的方案,我们只做 reducer 方法(在实例化 state 是需要传入)时,就可以这么做区分
代码语言:javascript
复制
AppState counterReducer(AppState state, dynamic action) {
  switch (action.runtimeType) {
    case IncrementAction:
      return state.copyWith(count: state.count + action.payload);
  }

  return state;
}
3.5 声明 store
  • 上面基本就是所有的准备步骤了,那么这里我们进入具体的使用
  • redux 的所有方案都是通过 store 沟通的,所以我们首先要先将 store 实例化
代码语言:javascript
复制
class FlutterReduxApp extends StatelessWidget {

  final store = Store<AppState>(counterReducer, initialState: AppState.initialState());

  @override
  Widget build(BuildContext context) {
	···
  }
}
3.6 获取与更新
  • 那么如何使用 store 呢?首先我们需要或 store 中存的对应数据
  • 这里我们需要从中获得当前数值 count ,具体实现如下
代码语言:javascript
复制
class FlutterReduxApp extends StatelessWidget {
  //步骤4 申明一个store,必须传入一个方法进去,其余的参数选填,这里选择初始化一下基础参数
  final store = Store<AppState>(counterReducer, initialState: AppState.initialState());

  @override
  Widget build(BuildContext context) {
    return StoreProvider(
        store: store, //绑定store
        child: MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: Text("Title"),
            ),
            body: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text("You have pushed the button this many times:"),
                  //当需要使用到共享数据的时候使用StoreConnector来获取数据
                  StoreConnector<AppState, String>(builder: (context, value) {
                    return Text(value, style: Theme.of(context).textTheme.display1);
                  }, converter: (Store store) {
                    return store.state.count.toString();
                  })
                ],
              ),
            ),
          ),
        ));
  }
}
3.7 触发
  • 能够显示数据之后,就剩下数据的更新了
  • 使用 redux 的方便在于,我们并需要专门设置 setState 方法,因为 redux 已经帮我们内置了
  • 我们只需要在传入对应参数即可,这里我们点击 floatingActionButton 后让数字 +1
代码语言:javascript
复制
class FlutterReduxApp extends StatelessWidget {
  
  final store = Store<AppState>(counterReducer, initialState: AppState.initialState());

  @override
  Widget build(BuildContext context) {
    return StoreProvider(
        store: store, //绑定store
        child: MaterialApp(
          home: Scaffold(
            floatingActionButton: StoreConnector<AppState, VoidCallback>(
              converter: (Store store) {
                return () => store.dispatch(IncrementAction(payload: 1)); //发送数据
              },
              builder: (BuildContext context, VoidCallback callback) {
                return FloatingActionButton(
                    onPressed: callback, child: Icon(Icons.add));
              },
            ),
          ),
        ));
  }
}
3.8 redux 对内存的优化
  • 使用 redux 前我们每次刷新页面,所有控件都需要重绘,导致对内存小号极大:
  • 而同样的逻辑改为 redux 后我们明显发现,只有需要修改的控件才会被刷新

四、方法中使用

  • 感谢评论区小伙伴提供,方法中获取并使用 store 中数据的方法:
代码语言:javascript
复制
void setName() { 
 	var store = StoreProvider.of<AppState>(context); 
 	store.dispatch(xxx()) 
}

五、总结

  • flutter_redux 有效的解决了控件到控件间冗长的参数传递,以及高度藕合带来的繁杂逻辑,极大的方便了我们编码,同时其刷新特性,能够很好的优化 app 内存使用
  • 为了方便大家学习,我把代码上传到了 githubflutter-redux-sample
  • 如果还有疑问,或者有更好的方法,欢迎大家在评论区提出
  • 感谢大家的三连或者关注支持,我们下期文章再见
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-03-21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、前言
  • 二、原理
  • 三、使用
    • 3.1 封装需要共享的数据
      • 3.2 封装需要发送的消息
        • 3.4 数据修改与分发
          • 3.5 声明 store
            • 3.6 获取与更新
              • 3.7 触发
                • 3.8 redux 对内存的优化
                • 四、方法中使用
                • 五、总结
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档