Flutter 状态管理调研总结

一, 候选状态管理组件简介

0. flutter_hooks

一个 React 钩子在 Flutter 上的实现:++Making Sense of React Hooks++

钩子是一种用来管理 Widget 生命周期的新对象,以减少重复代码、增加组件间复用性,允许将视图逻辑提取到通用的用例中并重用,这使得编写小部件更快、更容易。适用于需要在多个组件中共享状态逻辑的场景,例如管理动画控制器、处理用户输入、管理生命周期等。

可以帮助开发者更好地组织和管理Widget状态和生命周期。它可以提高代码的可读性和可维护性,并且减少了使用传统的 StatefulWidget 时的样板代码量。

Flutter Hooks 相对于传统的 StatefulWidget 带来了一系列改进,主要包括:

  1. 减少样板代码 :Flutter Hooks 通过使用钩子(Hooks)允许在无状态(StatelessWidget)中管理状态和生命周期,从而减少了创建 StatefulWidget 及其相应的 State 类所需的样板代码。

  2. 提高代码复用性:Hooks 可以在不同的 Widget 中共享,使得逻辑代码更易于复用,有助于代码组织和维护。

  3. 简化状态管理 :Hooks 提供了如 useStateuseEffect 等函数,使得状态的管理和生命周期事件的处理更为直观和简洁。

  4. 改善可测试性:由于 Hooks 的逻辑与 Widget 的构造分离,这使得单元测试更加简单,因为可以单独测试 Hooks 的逻辑。

  5. 兼容现有的 Flutter 架构:Flutter Hooks 设计为与现有的 Flutter 架构兼容,可以在不改变现有代码结构的情况下逐步采用。

  6. 提高性能:Hooks 允许开发者更精细地控制何时以及如何重新构建 Widget,这可能导致性能优化。

  7. 促进声明式编程:Hooks 鼓励声明式编程风格,使得代码更易于理解和预测。

局部和响应式 状态管理 BLoC

变种: flutter_hooks_blochydrated_blochooked_blocvelocity_bloc

BLoC 是一种流行的架构模式,通过使用流来管理状态,将 UI 组件与业务逻辑解耦。它涉及三个主要组件:Stream、Sink 和 BLoC 本身,后者充当 UI 和数据源之间的中间人。

Bloc 基于事件的概念。你需要定义事件和状态,然后实现事件到状态的映射,从 UI 层发出事件,Bloc 接受这些事件,并根据当前状态和接收到的事件通过 mapEventToState 函数来决定下一个状态。

hooked_bloc 简化了 Bloc/Cubit 的注入和使用,它基于在 React Native 中首次引入的 hook 概念,允许将视图逻辑提取到通用的用例中并重用,这使得编写小部件更快、更容易。hooked_bloc 通过提供一组基于 hook 的 API 来实现依赖注入和状态管理,这些 API 可以帮助开发者更有效地组织代码,减少冗余,并促进代码的可重用性。

优点:

分离关注点和改进代码组织。

增强的测试性和可维护性。

支持跨多个 UI 组件的业务逻辑重用。

缺点:

学习曲线陡峭,特别是对于刚接触响应式编程概念的开发人员。

与其他解决方案相比,增加了样板代码和复杂性。

需要额外的包,如 rxdart 或 flutter_bloc 库。

全局和声明式 状态管理 Riverpod

变种: hooks_riverpod

Provider是一个流行的Flutter依赖注入库,主要是基于InheritedWidget实现的。ChangeNotifierProvider是它提供的一种Provider,用于将ChangeNotifier的实例提供给其子Widget,并在状态变化时通知它们。当你使用ChangeNotifierProvider时,你会在Widget树中的某个节点处提供一个ChangeNotifier实例,并且只有当notifyListeners被调用时,该Provider的依赖者(子Widget)才会重建。

Riverpod 是一种基于提 Provider 的状态管理解决方案,是 flutter_riverpod 包中提供程序的替代品。它利用 Provider 的概念来管理和共享部件间的状态,重点关注简单性、可扩展性和可测试性。

riverpod相比 Provider 不同的是,它不依赖于InheritedWidget。所有的providers都定义在全局范围内,你会使用ProviderScope来确保providers可以在Widget树中任何地方使用。

ProviderScope是一个状态容器,创建了一个状态存储,你可以在此之下的Widget树中任何地方通过context.readcontext.watchConsumer等API访问providers。

RiverPod 与 Flutter Hooks 库结合,提供了灵活的响应式状态管理解决方案,RiverPod 处理依赖注入和状态管理,而 Hooks 简化了小部件的组合和响应式更新。

优点:

与其他基于 provider 的解决方案相比,易于设置和减少样板代码。

通过模拟 provider 和依赖注入提高了可测试性。

允许对小部件的重建进行细粒度的控制。

缺点:

与其他状态管理选项相比,相对较新,可能导致社区资源较少。

与 Provider 或 BLOC 等更成熟的解决方案相比,生态系统和社区支持有限。

需要像 flutter_riverpod 这样的额外包进行集成。

Cubit

变种: async_cubitsside_effect_cubit

Cubit 是 Flutter 团队提供的基于 BLoC 模式的状态管理库,它强调简单性,遵循单向数据流方法,使用 Stream 和 Sink 来处理状态变化和更新。

它不依赖于事件的概念,而是直接对函数调用做出响应。在 Cubit 中,你直接调用一个函数来改变状态。这个函数内部会执行一些逻辑,并最终调用 emit 来发出新的状态。

Bloc 相比,Cubit 不需要定义事件,也不需要通过事件来触发状态变化,因此在实现上更为简洁。由于其简洁性,特别适用于那些不需要复杂事件处理的场景,可快速实施状态管理。

优点:

轻量级且易于理解,特别是对于熟悉 BLoC 模式的开发人员。

与传统的 BLoC 相比,简化了语法并减少了样板文件。

性能和测试性良好。

缺点:

与更全面的状态管理解决方案相比,功能有限。

可能不适合高度复杂的状态管理场景。

较少的社区支持和第三方软件包。

RiverBloc

Bloc与Riverpod的结合使用

Bloc和Riverpod是两种流行的状态管理库,它们可以在Flutter应用中单独使用,也可以结合使用以发挥各自的优势。Bloc侧重于事件驱动的状态管理,适合处理复杂的业务逻辑,而Riverpod提供了依赖注入和状态管理的解决方案,强调简洁性和性能。

结合使用的策略

结合使用Bloc和Riverpod时,可以将Bloc用于管理应用的核心业务逻辑,而使用Riverpod来管理UI相关的状态或提供服务。例如,可以将Bloc用于处理用户输入、网络请求和数据转换等,而将Riverpod用于提供国际化、主题管理或数据缓存等服务。

Bloc和Riverpod的职责范围划分

在结合使用Bloc和Riverpod时,您可以根据它们各自的设计哲学和优势来划分职责范围。Bloc通常用于处理复杂的业务逻辑,它采用单向数据流模式,将状态管理和业务逻辑分离,有助于维护和测试。Riverpod则是一个状态管理库,它提供了更简洁的API和更好的性能,适合管理跨多个屏幕和组件的状态。

Bloc的职责

处理复杂的业务逻辑:Bloc适合处理那些需要响应用户输入、系统事件或其他状态变化的复杂逻辑。

状态和事件分离:Bloc通过区分状态和事件来管理应用状态,有助于保持代码的清晰结构。

可测试性:由于Bloc的状态和逻辑是分开的,因此它们更容易进行单元测试。

Riverpod的职责

管理共享状态:Riverpod擅长管理应用中的共享状态,特别是那些不经常变化的状态,如配置信息或用户偏好设置。

性能优化:Riverpod通过缓存和延迟计算来优化性能,减少不必要的渲染和计算。

灵活的状态管理:Riverpod提供了多种Provider类型,可以根据不同的需求选择合适的状态管理策略。

职责范围的划分建议

核心业务逻辑使用Bloc:对于应用的核心功能,如用户认证、商品购物车等,使用Bloc来处理相关的状态和事件。

共享状态和配置使用Riverpod:对于需要在多个屏幕间共享的状态,如语言设置、主题颜色等,使用Riverpod来管理。

数据流和状态更新:Bloc可以处理复杂的数据流和状态更新逻辑,而Riverpod可以用于简单的状态读取和监听。

通过上述分工,您可以充分利用Bloc和Riverpod的优点,构建一个既高效又可维护的Flutter应用状态管理体系。在实际应用中,这种组合可以提供更好的灵活性和可扩展性,适应不断变化的应用需求。

Riverbloc 是基于 Riverpod 提供的 BlocProvider 的实现,旨在简化从 flutter_blocflutter_riverpod 的迁移过程。Riverbloc 利用 Riverpod 的优势,如依赖注入和更简洁的 API,来提供一个更现代和灵活的状态管理解决方案。

是 Bloc 模式在 Riverpod 生态系统中的一个实现,结合了 BLoC 和 Riverpod 的概念,提供了一个简化和高效的状态管理解决方案,它利用 Riverpod 的提供者系统,并将其与 BLoC 的反应流相结合,使强大的状态管理功能成为可能。

Riverbloc 基于声明式编程,它允许开发者通过声明式的方式来管理应用的状态。Riverbloc 强调的是状态的单一来源原则,即每个状态都由一个唯一的提供者(Provider)管理。它提供了丰富的提供者类型,包括但不限于 StateProvider, FutureProvider, StreamProvider, ChangeNotifierProvider 等,以及一系列的构建器和消费者小部件来帮助开发者构建响应状态变化的 UI。

优点:

提供 BLoC 和 Riverpod 的优点,提供灵活而强大的状态管理解决方案。

允许对小部件的重建进行细粒度的控制。

与其他 Flutter 库(如 flutter_hooks )集成,以增强开发体验。

缺点:

相对较新的库,社区支持和资源有限。

需要熟悉 BLoC 和 Riverpod 的概念。

对于刚接触响应式编程的开发人员来说,学习曲线可能会更陡峭。

二,对比

|-----------|--------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------|---------------------------------------------------|
| 对比维度 | hooks_riverpod | flutter_hooks_bloc | riverbloc |
| 状态管理框架 | 基于Riverpod的响应式缓存和数据绑定框架 | 结合Hooks和Bloc/Cubit的状态管理库 | 基于Riverpod的BlocProvider实现 |
| 目的 | 简化异步代码处理,提供高级场景支持,分离逻辑与UI,确保代码可测试、可扩展和可重用 | 简化Bloc/Cubit的注入和使用,利用Hooks提高代码复用性和开发效率 | 便于迁移自flutter_bloc到flutter_riverpod的BlocProvider实现 |
| 核心概念 | Riverpod Provider、HookConsumerWidget | Hooks、Bloc/Cubit,HookWidget | BlocProvider,StateNotifierProvider |
| 状态更新通知 | 使用StateNotifier或ChangeNotifier来管理状态,并提供了ref.watch和ref.read等方法来观察和读取状态 | 通过Bloc/Cubit的状态变化通知UI重建,使用事件(Event)来触发状态的变化,并通过Bloc的emit方法来更新状态 | 通过Riverpod Provider的变化自动通知UI重建 |
| 状态管理策略 | 提供多种Provider类型,如FutureProvider、StreamProvider等,使用ConsumerWidget或HookConsumerWidget来消费这些状态。 | 支持Bloc和Cubit模式,提供了Bloc类和BlocProvider,开发者可以通过这些类来创建Bloc实例,并使用BlocBuilder或BlocListener来构建响应Bloc状态变化的UI。 | 结合Riverpod的状态管理策略,适用于Riverpod生态系统 |
| 与Hooks的整合 | 提供HookConsumerWidget,结合Hooks的状态管理能力 | 使用Hooks提供的useBloc等函数简化Bloc/Cubit的使用 | 需要参考左边两个,依赖flutter_hooks,hooks_riverpod单独引用使用 |
| 社区支持和文档 | 活跃的社区支持,详细的官方文档 | 社区支持,官方文档提供Bloc/Cubit的使用指导 | 社区支持,官方文档提供Riverpod的使用指导 |
| 推荐场景 | 适合需要响应式数据绑定和缓存的应用程序 | 适合需要Bloc/Cubit模式和Hooks优势的应用程序 | 适合需要从flutter_bloc平滑过渡到Riverpod的应用程序 |

hooks_riverpod和hooks_bloc在代码可读性和维护性方面哪个更胜一筹?

hooks_riverpodhooks_bloc都是用于Flutter应用程序的状态管理库,它们分别基于Riverpod和Bloc架构,并提供了与Hooks的集成,以提高代码的可读性和维护性。

特点对比
  • hooks_riverpod

  • Riverpod是一个状态管理库,它允许开发者以声明式的方式管理应用程序状态,并且可以与Hooks结合使用,以在函数组件中管理状态。Riverpod强调的是全局状态管理,并且提供了灵活的状态提供者和消费者机制。

  • hooks_riverpod通过Hooks提供了更简洁的API,允许开发者在不创建StatefulWidget的情况下管理状态,这有助于减少样板代码并提高代码的可重用性。

  • hooks_bloc

  • Bloc是一个响应式编程框架,它通过使用可观察的流和可转换的流来管理应用程序的状态。hooks_bloc是Bloc的Hooks版本,它允许开发者在函数组件中使用Bloc的状态管理模式,从而提高代码的模块化和可测试性。

  • hooks_bloc的设计哲学是将状态管理封装在Bloc对象中,这有助于保持UI的简洁性,并且通过流的使用,可以清晰地处理状态的变化和用户的交互。

可读性和维护性
  • hooks_riverpod

  • Riverpod的声明式状态管理和Hooks的结合提供了一种直观的方式来处理状态,这可能有助于提高代码的可读性,尤其是在处理复杂的状态逻辑时。

  • Riverpod的状态提供者和消费者机制可以清晰地区分状态的来源和使用点,这有助于维护和追踪状态的流动。

  • hooks_bloc

  • Bloc的响应式编程模型通过流的使用,可以让状态变化的逻辑更加集中和清晰,这有助于维护状态逻辑,并且通过可转换的流,可以更容易地处理异步操作和复杂的业务逻辑。

  • hooks_bloc的模块化设计有助于隔离不同的业务逻辑,使得代码更加模块化,便于维护和扩展。

结论

选择hooks_riverpod还是hooks_bloc取决于个人或团队的偏好以及项目的具体需求。如果项目需要更灵活的全局状态管理和对状态提供者有更细粒度的控制,hooks_riverpod可能是更好的选择。而如果项目倾向于使用响应式编程模式来处理复杂的业务逻辑,并且需要清晰的状态流,hooks_bloc可能更适合。在实际应用中,两种库都可以提供良好的代码可读性和维护性。

三,后期迁移成本

要将Flutter Bloc转换为Riverpod,您需要遵循以下步骤:

  1. 识别Bloc的状态和事件:首先,您需要识别Bloc中的状态和事件。这些是Bloc逻辑的核心部分,您将在Riverpod中重建它们。

  2. 创建Riverpod StateNotifier :使用Riverpod的StateNotifier来创建一个新的状态控制器。这个控制器将负责管理状态的逻辑,类似于Bloc中的Bloc类。

  3. 迁移Bloc的逻辑 :将Bloc中的mapEventToState逻辑迁移到StateNotifier中。这通常涉及到根据接收的事件更新状态。

  4. 替换BlocProvider :在您的应用程序中,将所有BlocProvider替换为Riverpod的StateNotifierProvider。这意味着您需要更新所有使用Bloc的BlocProvider实例,以便它们使用新的Riverpod StateNotifierProvider

  5. 更新 UI 绑定 :修改您的UI代码,以便它使用Riverpod的ConsumerHookConsumerWidget来订阅状态更改,而不是Bloc的BlocBuilderBlocListener

参考天工:

  1. 局部和响应式 状态管理 BLoC

https://www.tiangong.cn/result/7596e186-d8e9-4d05-a545-bf4f0c7f45df

  1. 全局和声明式 状态管理 Riverpod

https://www.tiangong.cn/result/6ec740bb-1f3f-4242-9d65-d22d67b04127

相关推荐
jcLee959 小时前
Flutter/Dart:使用日志模块Logger Easier
flutter·log4j·dart·logger
tmacfrank10 小时前
Flutter 异步编程简述
flutter
tmacfrank10 小时前
Flutter 基础知识总结
flutter
叫我菜菜就好11 小时前
【Flutter_Web】Flutter编译Web第三篇(网络请求篇):dio如何改造方法,变成web之后数据如何处理
前端·网络·flutter
AiFlutter15 小时前
Flutter-底部分享弹窗(showModalBottomSheet)
java·前端·flutter
m0_748247802 天前
Flutter Intl包使用指南:实现国际化和本地化
前端·javascript·flutter
迷雾漫步者2 天前
Flutter组件————PageView
flutter·跨平台·dart
迷雾漫步者2 天前
Flutter组件————FloatingActionButton
前端·flutter·dart
coder_pig2 天前
📝小记:Ubuntu 部署 Jenkins 打包 Flutter APK
flutter·ubuntu·jenkins
捡芝麻丢西瓜2 天前
flutter自学笔记5- dart 编码规范
flutter·dart