Flutter开发笔记flutter

Flutter中状态管理的理解

2022-06-13  本文已影响0人  直男程序员
aykff-l7m6b.png

一、状态管理认知

1、核心解耦

我理解的状态管理核心思想是解耦。 和别的框架一样,Flutter中的状态管理主要是对逻辑、数据等进行解耦,以适应复杂业务的开发及维护。

2、对比其它框架

最经典的解耦就是MVC了,划分为三个模块:

3、Flutter状态管理

Flutter中的状态管理主要是对逻辑层状态层页面层行为层等进行划分:

不同的解耦层可以组合成不同的模式,如MVC是由逻辑层、数据层、页面层组成,在Flutter中可以分为极简模式(页面层+逻辑层)、标准模式(页面层+逻辑层+状态层)、严格模式(页面层+逻辑层+状态层+行为层)、强迫症模式(页面层+逻辑层+状态层+行为层+ Reducer层),几种模式各有优缺点,下面我会结合具体的状态管理框架详细的讲下这几种模式。

二、状态管理模式

2.1、极简模式

状态管理-极简模式.png

从上图可以看出极简模式由逻辑层+页面层组成,各自的职责如图所示,非常的简洁,对于不是太复杂的业务使用与用该模式开发,如果一些简单的页面也用复杂的模式感觉有点生搬硬套了,有的分层完全是不需要的,也造成了内存的浪费。
现在较为流行的状态管理框架也是按照极简模式划分的,如providergetx,两者的区别不大,不过在选择使用时选provider可能需要能hold的住InheritedWidget,选getx可能需要能hold的住依赖注入,回收GetXController

2.2、标准模式

状态管理-标准模式.png

从上图可以看出标准模式由 逻辑层+页面层+状态层组成,各自的职责如图所示,相比极简模式,标准格式多了状态层,状态层主要是存储所需的状态变量。标准模式类似于经典的MVC的分层,用的十分普遍,能够很好的解耦。
常见的框架有cubitprovidergetx

2.3、严格模式

状态管理-严格模式.png

从上图可以看出标准模式由 逻辑层+页面层+状态层+行为层组成,各自的职责如图所示,相比标准模式,严格格式多了一个行为层,行为层从图中可以清楚的看出主要是为了处理交互事件,那为什么要多出这一层呢?其实在Flutter中使用标准模式时会存在一个问题,很多的交互事件都是深埋在各个widget中,查找起来非常不变,事件少了还好,如果后续越来越复杂事件越来越多那就成了一团麻了。有了行为性这一分层,可以很好的处理交互事件,页面有什么交互事件,交互事件如何处理只需到Action文件中查找即可,对于后期的维护来说十分方便。
常见的状态管理框架:BlocReduxfish_redux

2.4、强迫症模式

状态管理-强迫症模式.png

从上图可以看出标准模式由 逻辑层+页面层+状态层+行为层+Reducer层组成,各自的职责如图所示,相比严格模式,强迫症模式多了一个Reducer层Reducer层主要是对数据进行处理并更新后刷新页面。从上图来看这个结构已经有点复杂了,为了解耦数据刷新这一层次,付出了巨大的成本
常见的状态管理框架:Reduxfish_redux

三、状态管理框架对比

3.1、Bloc

BLoC是谷歌提出的一种设计模式,利用stream流的方式实现界面的异步渲染和重绘,我们可以非常顺利的通过BLoC实现业务与界面的分离。在使用BLoC前需要了解三个重要的概念,分别是 CubitBlocObserverBLoC

3.1.1、Cubit

Cubit是管理状态数据的BlocBase 子类,它可以管理任意类型的数据,包括基本类型到复杂对象。在Cubit调用 emit 构建新的状态数据前需要给状态数据一个初始值。当状态数据发生改变的时候,会触发 Cubit 的 onChange 回调,如果出现错误则会触发 onError 回调。

class CounterCubit extends Cubit<int> {
  CounterCubit() : super(0);

  void increment() => emit(state + 1);
  void decrement() => emit(state - 1);

  @override
  void onChange(Change<int> change) {
    super.onChange(change);
    print(change);
  }

  @override
  void onError(Object error, StackTrace stackTrace) {
    print('$error, $stackTrace');
    super.onError(error, stackTrace);
  }
}
3.1.2、BlocObserver

BlocObserver 可以监听所有的Cubit的变化,从而使得我们可以同时监听多个Cubit

3.1.3、Bloc

Bloc也是继承 BlocBase 的类,但相比 Cubit 来说更为高级一些。它使用的是 events 而不是暴露的函数来更新状态。在 Bloc 内部,有一个onEvent 方法,在这个方法里,通过 EventTransformerevent转换为更新状态的方法来刷新状态数据。每个event都可以有对应的 EventHandler来处理该 event,完成后再通过 emit 触发通知状态更新。当状态转变前会调用 onTransition,在这里会有当前的状态,触发更新的 event 和下一个状态。

Bloc 的设计来看,使用了函数Cubit形式和事件Bloc形式的方式来驱动状态数据更新,然后再通过emit通知状态更新,通过这种方式解耦 UI 界面和业务逻辑。

优缺点分析:
优点:
缺点:

3.2、Provider

Provider是Flutter官方开发维护的,也是近些年官方最为推荐的状态管理库。它对InheritedWidget进行了上层封装,致力解决原生setState方案的props臃肿、展示与逻辑耦合问题。使用时需在项目中引入provider这个库。

Provider将页面分为业务和视图两层,并定义NotifierConsumer两个核心概念:Notifier负责实现业务逻辑,且在数据更新时发出通知。Consumer负责实现界面逻辑,并在数据更新时更新自身,以及用户交互时调用Notifier方法。

优缺点分析:
优点:
缺点:

3.3、GetX

GetX 是 Flutter 上的一个轻量且强大的解决方案,也是我现在项目中正在使用的框架,在Flutter状态管理中绝对算是异军突起,一经发布就因其简单且全面的优势,引得一大批簇拥者。GetX可以称之为全家桶式的框架,具有以下多种功能:

3.3.1、路由管理

GetX内部实现了路由管理,这个是非常重要的,这样我们就不需要使用其他第三插件,而且GetX的路由管理非常简单,代码也简洁。

/// 跳转新页面
/// 第一种方式 进入新页面 直接页面
Get.to(TestPage());
/// 第二种方式 进入新页面 配置路由名称  建议这种统一配置
Get.toNamed(Routes.TestPage);
/// 弹出当前页,并将一个新的[page]推入堆栈,就是删除就页面,使用新页面
Get.off(TestPage());
/// Push a [page]和弹出几个页面在堆栈中,就是进入新页面,删除之前进栈的页面。比如场景(注册-手机号-其他注册信息-注册完了直接到主页,之前页面全部删掉。)
Get.offAll(TestPage());
/// 同上,就是传路由名称
Get.offAllNamed(FXRoutes.TestPage);
/// 返回上一面 就一句
Get.back()
3.3.2、状态管理

使用getx的状态管理,我一般一个page对应一个logic, logic需要继承 GetxController,该logic来处理逻辑并控制page,目录如下:

GetX状态管理.png

将页面和logic管理起来GetX使用的是依赖注入,有两种方式可以实现:
1、在view中使用依赖注入和logic关联,然后在获取到logic中的state,从而view中的交互事件直接调取logic中的方法进行处理,state用于刷新页面UI。

final logic = Get.put(TestPageLogic());
final state = Get.find<TestPage>().state;

2、在路由中绑定

GetPage(
        name: FXRoutes.TestPage,
        page: () => TestPage(),
        /// 主要代码是这个 绑定
        binding: BindingsBuilder(() => {
              Get.lazyPut<TestPageLogic>(
                  () => TestPageLogic())
            })),

使用GetView可以直接使用logic

/// 页面继承GetView<> 传依赖注入的控制器 这样就可以直接使用了,会发现这边没有 Get.put,或者Git.find, 使用的时候直接logic。 看源码可以知道GetView内部已经帮我们实现了。
class TestPage extends GetView<TestPageLogic> {
 @override
  Widget build(BuildContext context) {

  }
}
优缺点分析:
优点:
缺点:

3.4、fish_redux

fish_redux是阿里咸鱼团队开发的一个状态管理框架,是基于 Redux 数据管理的组装式 flutter 应用框架, 它特别适用于构建中大型的复杂应用。

它的特点是配置式组装。 一方面我们将一个大的页面,对视图和数据层层拆解为互相独立的 Component|Adapter,上层负责组装,下层负责实现; 另一方面将 Component|Adapter 拆分为 View,Reducer,Effect 等相互独立的上下文无关函数,结构非常清晰,适合团队开发,易与后期的维护。

使用fish_redux进行开发,拆分的文件目录为:

fish_redux.png

在开发中可下载 FishReduxTemplate插件,可快速生成对应的文件:

FishReduxTemplateu.png

fish_redux相比其它框架多了actionreducer层,其中action层主要是行为层,统一转发处理交互事件,我认为这一层还是很有必要的,多了一层从框架端来说复杂度是提高了,但是对于使用者来说却是结构清晰了,如果没有行为层,交互事件大多都埋在各种widget中,这样找起来非常不方便,而且随着后期的迭代也会变得越来越难维护,有了行为层就清晰多了。对于reducer层我保留意见,可能是水平达不到,我没有感受到这层妙处在哪。

优缺点分析:
优点:
缺点:

[注]:选择哪种状态管理框架没有准确的答案,其受难易程度、可维护性、开发成本、性能、应用场景、团队技术栈等因素的影响,所以适合自己的才是最好的。

上一篇下一篇

猜你喜欢

热点阅读