Flutter状态管理学习手册(二)——Redux

Flutter之fish redux状态管理浅析 什么是Flutter? Flutter 是来自谷歌的一个出色的跨平台框架,可用来为移动、桌面和 Web 平台构建应用程序。   目前,Flutter在移动端的应用比较成熟,阿里的咸鱼、美团、头条等顶级互联网公司都有实践应用,虽然生态资源方面不如React Native,但发展势头非常迅猛,流畅的性能体验,以及苹果、安卓代码的一致性方面都令人印象深刻。   虽然Web端和桌面端的跨平台应用仍未达... 阅读详情

上一篇讲到了一个简单的状态管理架构—— ScopedModel , 当然,这种简单的架构会用在商业项目中的概率比较小,本篇则讲述另一个架构: Redux ,一个优雅且实用的状态管理框架。本篇 Demo 地址:https://github.com/windinwork/flutter_redux_app

一、Redux 的准备工作

Redux 的概念源于 React,对于不是从事前端工作或者没有接触过 React 的人要理解 Redux 会比较繁复。对于不了解 Redux 的小伙伴,这里有两篇很不错的文章介绍了 Redux 的概念和相关知识:

Redux 入门教程(一):基本用法

Redux 入门教程(二):中间件与异步操作

二、Redux的概念

学习后 Redux 可以了解到,Redux 主要由涉及下面几种概念:

  • Store,是保存数据的地方。整个应用只能有一个 Store 。Store 有十分重要的方法 dispatch(action) 来发送 Action。
  • State,是某个时间点的数据快照, 一个 State 对应一个 View。只要 State 相同,View 就相同。
  • Action,是 View 发出的通知,通过 Reducer 使 State 发生变化。
  • Reducer,是一个纯函数,接受 Action 和当前 State 作为参数,返回一个新的 State。
  • Middleware,中间件,它的操作在发出 Action 和执行 Reducer 这两步之间发生,用于增加额外功能,如处理异步操作或者打印日志功能等。

Redux 的工作流程如图所示,先用户发出 Action ,Store自动给 Middleware 进行处理,再传递给 Reducer , Reducer 会返回新的 State ,通过 Store 触发重新渲染 View。这里的 View 在 Flutter 中以 Widget 的形式存在。

以上这部分是 Redux 的内容,比较容易理解。

三、Flutter中Redux的使用

在 Flutter 中,我们除了引入 redux 第三方库之外,还要引入 flutter_redux 第三方库 ,并且,为了对异步操作有更好的支持,还要引入 redux_thunk 库作为 Middleware ,对 thunk action 有更好的支持。

下面来了解 flutter_redux 中的概念。

  1. StoreProvider ,是一个基础 Widget ,一般在应用的入口处作为父布局使得,用于传递 Store 。

  2. StoreConnector ,一个可以获取 Store 的 Widget ,作用是响应 Store 发出的状态改变事件来重建 UI。

  • StoreConnector 中有两个标记为@required 的参数,一个是 converter , converter 用于将 store 中的 state 转化为 viewModel,另一个是 builder,builder 的作用是将 viewModel 进一步转化为 UI 布局。

  • StoreConnector 有一个值得一提的函数:onInit,在这个函数中可以执行初始化操作。

  1. 对于异步操作,我们引入了 redux_thunk 库,redux_thunk 库是一个中间件,它会处理 thunkAction。thunkAction 是只包含一个 Store 类型参数的函数。

通过 StoreProvider 和 StoreConnector 就可以在 Flutter 实现 Redux 的功能了,接下来是具体实践。

四、Redux 的实践

这里以常见的获取列表选择列表为例子。一个页面用于展示选中项和跳转到列表,一个页面用于显示列表。

1. 引入 Redux 的第三方库

  redux: ^3.0.0
  flutter_redux: ^0.5.3
  redux_thunk: ^0.2.1

2. 创建 Store

Store 全局只有一个,这里封装一个创建 Store 的方法。创建Store时,传入 Reducer ,初始化的 State 和 Middleware 。

Store<AppState> createStore() {
  return Store(appReducer, initialState: AppState.initial(), middleware: [
    // 引入 thunk action 的中间件
    thunkMiddleware
  ]);
}

3. 创建 State

State 状态,需要创建一个 AppState,作为整个应用的 state,除此之外,根据不同的页面可以有不同的 State,比如有一个列表页面 ListPage ,就可以有一个列表状态 ListState ,并且 ListState 会放在 AppState 中作为成员变量进行管理。

// app state
class AppState {
  ListState listState;

  AppState(this.listState);
}
// list state
class ListState {
  bool _init = false; // 列表初始化标志
  List<String> _list = []; // 列表数据
  String _selected = '未选中'; // 选中的列表项

  ListState(this._init, this._list, this._selected);
}

4. 创建 Action

Action 是 Widget 在用户操作后发出的通知。对于 ListPage 页面,创建一个 list_action.dart 文件,用于存在可发出的 Action 。在示例中,需要用到两个 Action 。一个是加载完成列表数据后发出的 Action ,用于刷新列表,一个是选中列表项时发出的 Action 。

/**
 * 加载完成列表数据
 */
class FetchListAction {
  List<String> list;

  FetchListAction(this.list);
}

/**
 * 选择列表
 */
class SelectItemAction {
  String selected;

  SelectItemAction(this.selected);
}

5. 创建 Reducer

Reducer 是一个带 State 和 Action 两个参数的纯函数,在这里,只需要关心根据传入的 Action 和旧的 State,返回一个新的 State。

和 State 一样,reducer 也分为应用的 app_reducer 和列表页面的 list_reducer。

Reducer是纯函数。在示例中通过 app_reducer 返回一个新的 AppState ,通过 list_reducer 分别对 FetchListAction 和 SelectItemAction 进行处理返回一个新的 ListState 。

AppState appReducer(AppState state, dynamic action) {
  return AppState(listReducer(state.listState, action));
}
ListState listReducer(ListState pre, dynamic action) {
  if (action is FetchListAction) {
    return ListState(true, action.list, pre.selected);
  }
  if (action is SelectItemAction) {
    return ListState(pre.isInit, pre.list, action.selected);
  }
  return pre;
}

6. 使用 Thunk Action

在创建 Store 时引入了 thunkMiddleware ,使得项目支持 thunk action。

项目中需要一个加载列表的异步操作,可通过 thunk action 实现具体操作,注意 ThunkAction 是只有一个 store 参数的函数。

ThunkAction<AppState> fetchList = (Store<AppState> store) async {
  // 模拟网络请求
  await Future.delayed(Duration(milliseconds: 3000));
  var list = [
    "1. Redux State Management",
    "2. Redux State Management",
    "3. Redux State Management",
    "4. Redux State Management",
    "5. Redux State Management",
    "6. Redux State Management",
    "7. Redux State Management",
    "8. Redux State Management",
    "9. Redux State Management",
    "10. Redux State Management"
  ];

  store.dispatch(FetchListAction(list));
};

7. UI 布局

通过以上代码,我们做好了 Redux 的准备工作。接下来便可以布局页面。

① 在 main.dart 中,要做的工作是创建 Store,和使用 StoreProider 作为根布局。

    // 创建Store
    var store = createStore();
    // 使用StoreProvider作为根布局
    return StoreProvider<AppState>(
        store: store,
        child: MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: ShowPage(),
        ));
  }

② show_page.dart ,用于显示选中的列表项和提供跳转到 ListPage 的按钮入口。

show_page.dart 中,选中的列表项的数据来自于 Store,所以这里使用 StoreConnector 来根据数据构建 UI 界面。

StoreConnector<AppState, String>(
  converter: (store) => store.state.listState.selected,
  builder: (context, selected) {
    return Text(selected);
  },
),

从上面可见,StoreConnector 需要两个泛型,一个是我们创建的 AppState,另一个是 ViewModel,这里我们直接将 String 作为 ViewModel。

StoreConnector 要定义两个函数,一个是 converter,从 Store 中拿出选中的列表项数据 store.state.listState.selected,另一个是 builder,将 converter 返回的 selected 进一步转化为界面:Text(selected)。

这就是 StoreConnector 的用法。

③ list_page.dart

list_page.dart 中的内容比较重点,里面实现了加载列表和点击列表的功能。

list_page.dart 中一开始要显示加载中的界面,等待数据成功加载后显示列表界面。这里也是用 StoreConnector 构建 UI。StoreConnector 将 AppState 转换为 ListState,通过 ListState 判断当前显示 loading 界面还是列表界面。

另外,在 StoreConnector 的 onInit 函数中执行加载列表的操作。

由于加载列表是一个异步操作,所以要用到之前定义的 fetchList 的 thunk action,这里通过 store.dispatch(fetchList) 来执行。

StoreConnector<AppState, ListState>(
    // 初始化时加载列表
    onInit: (store) {
  if (!store.state.listState.isInit) {
    store.dispatch(fetchList);
  }
  // 将store的state转化为viewModel
}, converter: (store) {
  return store.state.listState;
  // 通过viewModel更新界面
}, builder: (contxet, state) {
  // 根据状态显示界面
  if (!state.isInit) {
    // 显示loading界面
    return buildLoad();
  } else {
    // 显示列表界面
    var list = state.list;
    return buildList(list);
  }
})

另外,点击列表时也要发出一个选中列表项目的 Action ,即之前定义的 SelectItemAction 。

var store = StoreProvider.of<AppState>(context);
store.dispatch(SelectItemAction(list[index]));
// 返回到上一级页面
Navigator.pop(context);

store.dispatch(action) 发出的 Action 经过 Middleware 和 Reducer 的处理后,转变成 State,StoreConnector 就会自动地根据 State 重建 UI。

这样,一个使用 Redux 架构的应用就基本成型了。完整代码可以参考https://github.com/windinwork/flutter_redux_app

五、总结

在 Redux 中,数据总是"单向流动"的,保证了流程的清晰。相对于 ScopedModel 的架构, Redux 无疑更加规范,更易于开发和维护。只是, Redux 会相对地增加复杂性,所以,简单小型的项目可以不需要去考虑引进 Redux 这种架构,但对于大型的 Flutter 项目来说, Redux 就十分有用的架构。

六、思考

由于 Redux 只有一个应用只有一个 Store ,所以应用需要对整个 AppState 进行维护,在大型客户端代码迭代过程中,会和组件化和单独模块编译运行这种需求相矛盾,这是否会阻碍 Redux 成为大型项目采用的主要架构的因素呢?

参考目录

Flutter Redux Thunk, an example finally.

Introduction to Redux in Flutter

官网推荐 Sample:inKino

【Flutter】Flutter Redux 入门:解决状态管理的问题 Flutter Redux 是 Redux 在 Flutter 中的实现。它提供了一些工具,使我们能够在 Flutter 应用中方便地使用 Redux。通过使用 Flutter Redux,我们可以更好地组织和管理应用的状态,使得代码更加清晰,更易于维护和测试。 阅读详情

相关推荐

Flutter 使用 Redux 的中间件实现异步状态管理

加入了中间件后,在异步完成后可以触发异步操作相关的Action,以便将异步结果通过Reducer处理后更新状态。引入中间件后,可以使得异步操作与界面交互分离,进一步降低的耦合性和提高了代码的可维护性

Flutter 跨平台技术研究 1764

Flutter i18n+redux实现国际化

Flutter官方提供的实现国际化有些繁琐,需要自己实现WidgetsLocalizations,并且国际化的strings都是在代码中写的,而i18n插件可以自动生成这些代码,并且国际化的strings也是使用文件以json形式配置。加以使用redux实现语言切换及持久化。 Android Studio安装i18n插件 安装后在菜单栏中会有如下图标,点击用于生成i18n代码 项目中设置国际化...

cj_286的博客 1034

flutter+getX+middleware-示例项目

flutter+getX+middleware-示例项目

在Flutter中封装redux的使用

最近发现了之前没写完的一个Flutter版APP,于是打算重构并继续开发,本文主要整理在Flutter中使用redux的一些开发经验。 参考 redux.dart flutter_redux 基础使用 跟在JS中使用Redux类似,主要分为下面几个步骤 定义Action 实现Reducer,接收Action并返回更新后的State 在组件中使用State,并订阅Store的变化,当数据变化时重新更...

663

从零完成 STM32 + ESP-01S + 云服务器 TCP 通信测试

STM32 通过 USART3 控制 ESP-01S 接入手机 2.4 GHz 热点,随后连接公网云服务器 8.152.204.86:9002。云端在同一 TCP 连接中连续收到 seq=1~6 的测试报文,5 个发送间隔平均约 5.4 秒,说明本次 TCP 上行链路已经打通。

weixin_51387720的博客 312

Seurat 单细胞转录组测序数据分析教程(三)——python(scanpy)

文章参考至,做了一个更详细的解读。本教程探讨了 scanpy 的可视化可能性,分为三个部分:嵌入的散点图(例如 UMAP、t-SNE)使用已知标记基因鉴定簇差异表达基因的可视化在本教程中,我们将使用来自 10x 的数据集,其中包含来自PBMC的 68k 个细胞。Scanpy 在其分布中包括该数据集的简化样本,该数据集仅包含 700 个细胞和 765 个高度可变的基因。该数据集已经过预处理和 UMAP 计算。在本教程中,我们还将使用以下文献标记:B细胞:CD79A、MS4A1。

coffeeii的博客 5828

Flutter完整开发实战详解(四、 Redux、主题、国际化)

这里也为想要学习Flutter的朋友们准备了两份学习资料《Flutter Dart语言编程入门到精通》《Flutter实战》,从编程语言到项目实战,一条龙服务!!

Android 开发架构 1531

matlab中高频变压器怎么找,干货|手把手教你绕制高频变压器

原标题:干货|手把手教你绕制高频变压器绕制一个变压器所需材料:磁芯、骨架、各种铜线、麦拉胶带。变压器参数:磁芯:EE22原边:134T(1-3脚),辅助:32T(5-4脚),输出:15T(10-9脚)原边电感:1380±10%uH漏感:≤44uH引脚分布图: 特别注意:绕制方法为网上下载,其中变压器绕制方法是对的,但其中存在着很多问题(比如,正规变压器的绕组的头和尾是要添加铁氟龙套管的,每一层之间...

weixin_30895121的博客 2125

Flutter之状态管理(Redux)flutter_redux

Flutter是Google(全球顶级互联网科技公司)的生的,后台够硬,毫无疑问Flutter即将或已经成为跨平台开发的主流,Flutter野心很大,不仅冲击着原生开发,而且很有可能会烧到Web前端。作为移动端开发者的你,如果不关注Flutter的话,实在说不过去啦! 跨组件状态共享(Provider)的应用 一、效果图 界面初始化状态 点击按钮发起一个Redux Action更新界面(即更新S...

XiNanHeiShao的专栏 2015

2022北京高考数学压轴题21题:Python暴力枚举验证k≥7的5种反例

本文探讨了2022北京高考数学压轴题21题的编程解法,通过Python暴力枚举验证k≥7的5种反例。文章详细介绍了m-连续可表数列的定义、问题转化与约束条件,并提供了暴力枚举算法设计和优化技巧,帮助读者理解如何用编程思维解决数学问题。

weixin_33552698的博客 233

【入门AUTOSAR网络管理测试】AUTOSAR网络管理规范需求解读

AUTOSARAutomotive Open System Architecture,汽车开放系统架构,由全球汽车制造商、部件供应商及其他电子、半导体和软件系统公司联合建立,致力于制定汽车电子软件标准的联盟。网络管理网络管理的目的是使网络中的ECU节点有序的睡眠和唤醒。在没有通信需求的时候睡眠,在需要通信的时候唤醒,可以节约汽车电池的电量。

测试领域技术分享 5166

Flutter 状态管理之Redux

Flutter中一切皆组件(Widget),二组件中又有无状态的StatelessWidget和有状态的StatefulWidget两种;今天我们就来说一说StatefulWidget中的State的状态管理。一般我们有两种方式对state进行管理,一种是自己管理,一种是交给父组件管理。 自己管理:也就是组件自身通过setState来管理状态,通过手动触发setState来进行U...

qq_19979101的博客 2115

ACS运动控制器编程 怎么学习

本文介绍了ACS运动控制器编程的完整学习路线,从零基础到实战应用。ACS是以色列高端多轴运动控制平台,适用于自动化设备、精密平台等项目。学习路径包括:1)安装官方软件SPiiPlusControlSuite;2)掌握轴、运动模式和指令三个核心概念;3)学习10个基础指令;4)编写首个运动程序;5)结合C#进行联合编程。进阶内容包括多轴同步、电子凸轮等工业应用,并推荐官方手册作为主要学习资源。通过7天的系统学习,即可掌握单轴运动控制,结合C#实现工业级设备开发。

StevenChen的博客 1318

flutter redux状态管理

本文介绍了Flutter中使用Redux的完整流程。

liao277218962的专栏 718

利用R语言通过holtwinters模型进行预测

使用Holt-Winters模型进行预测的第一步是对模型进行拟合。该函数需要两个参数:您的时间序列数据和一个“seasonal”参数,该参数指示您的数据的周期性(例如,如果您的数据按月记录,则应将“seasonal”参数设置为12,因为一年有12个月)。拟合模型后,您可以使用“forecast()”函数进行预测。该函数需要两个参数:您的拟合模型以及您要进行预测的时间段的长度。要使用Holt-Winters模型,您需要安装并加载“forecast”包。以下是进行Holt-Winters模型预测的示例代码。

Mrrunsen的博客 1696

Python爬虫教程:抓取地方政府网站的公开文件与政策信息

Web爬虫是指一种自动化脚本,用于模拟人类浏览器访问网页、提取网页内容的数据抓取工具。发送请求到目标网页;获取网页内容;解析网页内容,提取所需数据;将数据保存或进一步处理。爬虫可以抓取各种形式的数据,如文本、图片、文件等。本教程将重点展示如何抓取地方政府网站上公开的政策文件、公告等信息。许多政府网站都会采取一定的反爬虫措施,防止大量数据被爬取。IP封锁:如果短时间内大量请求来自同一IP,可能会被封锁。验证码:一些网站会使用验证码来验证访问者是否为机器人。动态加载。

2201_76125261的博客 1981

Flutter主流状态管理框架provider、bloc、redux对比

为什么需要状态管理 provider bloc redux 对比 总结 为什么需要状态管理 在了解和进行Flutter状态管理框架对比之前呢,我们先来问自己一个问题:为什么需要状态管理? 如果我们的应用足够简单,Flutter作为一个声明式框架,我们或许只需要将数据映射成视图就可以了。我们可能并不需要状态管理,就像下面这张图: 但是随着功能的增加,我们的应用程序将会有几十个甚至上百个状态。这个时候我们的应用将会变成这样: 在这种情况下我们很难再清楚的...

唐僧的专栏 6512

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

Flutter Redux与其他状态管理方案对比:什么场景下选择Redux?

在Flutter应用开发中,状态管理是一个至关重要的核心话题。随着应用复杂度的增加,如何高效、可维护地管理应用状态成为了开发者面临的关键挑战。Flutter Redux作为一个基于Redux架构的状态管理库,为Flutter应用提供了强大的状态管理解决方案。本文将深入探讨Flutter Redux与其他主流状态管理方案的对比,帮助你了解在什么场景下选择Redux是最佳决策。 ## 🔍 Flut

gitblog_00930的博客 968

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Flutter for OpenHarmony 实战:flutter_redux 全局状态机与单向数据流

本文介绍了在HarmonyOS NEXT平台上使用Flutter_redux进行状态管理的实战方法。文章从Redux的三大核心原则(单一数据源、Actions声明变化、Reducers纯函数处理)入手,通过构建"任务管理中心"和"用户中心"两个案例,详细展示了状态定义、Actions派发和Reducer处理的完整流程。重点讲解了StoreConnector在UI连接中的使用技巧,以及ViewModel聚合模式在复杂状态管理中的应用。最后针对鸿蒙平台特性,提供了性能优化

2609_95049439的博客 1万+

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Flutter 状态管理

目录 一、状态管理简介 1.1 为什么需要状态管理 1.1.1 Flutter与adr/ios UI框架区别 1.1.2 状态管理框架使用场景 1.2 需要解决的问题 二、状态管理框架现有方案调研 2.1 状态管理框架 2.1.1 官方方案 2.2 市场方案调研 2.2.1 flutter_bloc 2.2.2 flutter_redux 2.2.3 fish_redux 一、状态管理简介 1.1 为什么需要状态管理 1.1.1 Flutter与adr/ios UI框架区别

zxx910509的博客 3903

【Flutter#状态管理】Flutter 状态管理全面解析

在 Flutter 中,状态指的是影响 UI 展示的数据。例如,用户的输入、应用的配置、从服务器获取的数据等。Flutter 的 UI 是响应式的,意味着 UI 会随着状态的变化而自动更新。Riverpod 是 Flutter 中用于状态管理的一个强大的工具库,由 Provider 的作者开发,旨在解决 Provider 的一些核心问题。

qq_17387479的博客 1729

Inputmask 5.x 使用指南:基于 Mask 语法的 JavaScript 输入掩码库

Inputmask 是一个纯 JavaScript 输入掩码(Input Mask)库,通过为 `<input>` 元素定义预设格式,引导用户按指定模式输入日期、数字、电话号码等数据。本文以仓库根目录 [README.md](https://link.gitcode.com/i/d940496f0e12229c4148cd29092d42a6) 为骨架,结合 [lib/](https://link

gitblog_00344的博客 1016

Flutter Redux状态管理最佳实践:提升应用性能的7个技巧

Flutter Redux是一个连接Widget和Redux Store的强大库,能够帮助开发者构建可预测、可维护的Flutter应用。本文将分享7个实用技巧,助你优化Flutter Redux应用性能,打造流畅用户体验。 [![Flutter Redux Logo](https://raw.gitcode.com/gh_mirrors/fl/flutter_redux/raw/4f32df61

gitblog_01015的博客 770

《Flutter学习笔记》redux状态管理 实现换肤

参考文档 https://guoshuyu.cn/home/wx/Flutter-4.html Redux 由于之前使用react框架,所以对于redux的一些概念会相对熟悉。对于不了解的朋友可以阅读以下文档进行入门redux: Redux 中文文档 精简版redux-tutorial redux主要涉及以下概念: Store: 用来保存数据的地方,整个项目只能有一个store,Stor...

qq_36546825的博客 512

Flutter架构示例:Redux状态管理深度解析

在Flutter应用开发中,状态管理一直是核心话题。本文将以brianegan的flutter_architecture_samples项目中的Redux实现为例,深入剖析Redux在Flutter中的最佳实践。 ## Redux基础概念 Redux是一种可预测的状态容器,其核心思想可以概括为三个基本原则: 1. **单一数据源**:整个应用的状态存储在一个不可变的对象树中 2. **状态只...

gitblog_00509的博客 460
上一篇: Flutter状态管理学习手册(一)——ScopedModel
下一篇: Flutter状态管理学习手册(三)——Bloc
Two212250511
博客等级 码龄14年 1粉丝 21原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值