前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Flutter 状态管理

Flutter 状态管理

原创
作者头像
莫空9081
发布于 2024-07-09 08:26:20
发布于 2024-07-09 08:26:20
2190
举报
文章被收录于专栏:iOS 备忘录iOS 备忘录

我之前对 Flutter 的状态管理一直比较头大,最近看到了一篇Flutter state management for minimalists | by Suragch | Medium文章,感觉文章真的很好,把为什么要进行状态管理以及什么是状态管理说的很通透,推荐大家看原文,这里是自己总结一下。

<!--more-->

什么是状态管理

老实说,之前看 Flutter 相关的文章和视频的时候,有些上来就推荐用 Bloc 的就很懵,没有前因后果,就告诉我要用这个东西,这东西用了有什么好处?这东西上手难度如何,这东西是必备的吗?和其他的状态管理库(比如GetX)对比有什么优点,等等之类的都不清楚,所以一直很难深入学习。

来看下图:

我本人是 iOS APP 开发,所以对于 MVVM 很熟悉,对比上图,UI Layer 是 View,Service Layer是 Model,所以 State Management Layer 就是 ViewModel,这样解释对比,我就对状态管理有了直观的理解,只是换了个名称,其实就是 ViewModel。

为什么要状态管理

那为什么要状态管理呢?其实理解了上面,就知道这其实不是个问题。由于项目使用MVVM所以需要 ViewModel。 同理由于采用了UI LayerState Management LayerService Layer这种架构设计,所以需要状态管理,所以真正的问题是为什么采用这种架构?而这个问题就简单了,因为采用这种架构设计清晰、更容易实现数据分离、容易测试、代码更容易复用。

UI LayerState Management LayerService Layer

Flutter

UI Layer是绘制 UI,尽量不要把逻辑写作 UI Layer中,最多就是写一些If else判断显示不同的 UI,而 UI 要显示什么,显示成什么样,则是state控制的。

UI Layer是把state显示给用户。所以解析、格式化字符串、存储数据之类的逻辑也不应该写在这一层中。

State Management Layer是负责数据和 UI 交互的,一方面把数据处理后显示到 UI 上,另一方面处理响应 UI的事件,对数据进行计算变更。这个地方是大部分逻辑应该存在的地方。使用State Managerment Layer时需要注意,虽然这层负责和 UI 的交互,但是不应该把UI Layer和他混在一起,简单的说,可以这么理解UI Layer通过 State Management Layer获取数据,处理数据,但是State Management LayerUI Layer了解不多,这样做的好处是,当重构UI Layer时,State Management Layer不受影响。

Service Layer,虽然大部分的逻辑在State Management Layer中,但是还有一部分逻辑是在这一层处理的,这一层可以理解为封装好的统一的数据层,里面可能是一个本地数据库、或者网络请求的数据,或者其他存储的数据。然后统一封装为Service Layer对外调用。通常做法是把Service Layer定义为Protocol或者interface,然后再由具体的Service实现这些协议或者接口,对于State Management Layer来说,只知道有这些协议或者接口,至于具体是怎么实现的,State Management Layer并不清楚。这样做的好处是,通过定义协议或者接口,可以更方便的实现分离,更方便的测试,比如可以在服务端没好的时候,通过 Service来实现Mock Fake Data进行测试。

作者推崇的Service Locator模式

回归主题,如何实现状态管理,即如何设计State Management Layer

首先再来思考一下State Management Layer的作用:

  1. UI Layer能够引用State Management Layer
  2. State Management Layer能够响应UI Layer的事件
  3. UI Layer能够通过State Management Layer监听状态变化
  4. 状态变化能够自动刷新 UI

下面一条条来看,如何处理:

UI Layer能够引用State Management Layer

这一步,很简单,只需要在对应Widget中声明对应的 State Manager 即可,这里有两种方式,

一种是普通的

代码语言:Swift
AI代码解释
复制
class MyPage extends StatefulWidget {
  // ... 
} 

class _MyPageState extends State<MyPage> {
  final manager = MyPageManager(); 
  // ...
}

一种是使用GetIt,单例模式的

代码语言:Swift
AI代码解释
复制
class MyPage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    final manager = getIt<MyPageManager>();
    // return ...
  }
}

使用GetItService Locator模式,可以参考How the GetIt service locator package works in Swift。这里感觉还是有些难以接受,因为之前开发 APP 时,被教导的是尽量少用单例,因为单例全局可访问,不可控,容易造成难以测试,难以维护。但是这里作者提出的是,在遵循下面规则的情况下,可以使用单例,来进行状态管理。

  • 不要直接通过UI Layer修改State Management中的State。要通过调用State Management Layer中的方法来修改。
  • 针对测试的问题,GetIt提供测试的方法,参考GetIt provides a way to test these classes

State Management Layer能够响应UI Layer的事件

UI Layer中的事件响应,直接通过调用State Management Layer中的方法来实现,如下:

代码语言:Swift
AI代码解释
复制
loginPageManager.submitUserInfo(username, password);

如果有需要在页面打开时初始化的逻辑,可以放在initState中来初始化。如下:

代码语言:Swift
AI代码解释
复制
@override 
void initState() { 
  super.initState(); 
  manager.doSomething(); 
}

UI Layer能够通过State Management Layer监听状态变化

这一步是比较麻烦的,直接使用Flutter自带的ValueNotifier或者ChangeNotifier来实现。使用方式如下:

代码语言:Swift
AI代码解释
复制
final myStateNotifier = ValueNotifer<int>(1);

myStateNotifier.value = 2;

也可以声明一个类继承自ValueNotifier,如下:

代码语言:Swift
AI代码解释
复制
class FavoriteNotifier extends ValueNotfier<bool> {
  // set initial value to false
  FavoriteNotfier(): super(false);

  // get reference to service layer
  final _storageService = getIt<StorageService>();

  // a method to call from the outside
  void toggleFavoriteStatus(Song song) {
    value = !value;
    _storageService.updateFavoriteSong(song, value);
  }
}

从上面的代码可以看出,所有的逻辑都封装在 Notifier中,对外暴露的是只一个调用方法。在State Management类中,只需要创建这个Notifier,然后调用Notifier中的方法即可。从而把复杂的逻辑进一步细化到具体的Notifier中,而不是直接成堆的混在State Management Layer中。

状态变化能够自动刷新 UI

最后,如果使用了ValueNotifier或者ChangeNotifier,那么UI的显示也需要做对应的调整。比如使用了ValueNotifier则需要用对应的ValueListenableBuilder Widget 来接收并响应对应Value的改变。

比如想要接收FavoriteNotifer的变化刷新 UI,则需要如下实现:

代码语言:Swift
AI代码解释
复制
class FavoriteButton extends StatelessWidget { 
  const FavoriteButton({Key? key}) : super(key: key); 
  @override Widget build(BuildContext context) { 
    final playPage = getIt<PlayPageManager>(); // 1 
    return ValueListenableBuilder<bool>( // 2 
      valueListenable: playPage.favoriteNotifier, // 3 
      builder: (context, value, child) { // 4, 5, 6, 7 
        return IconButton( 
          icon: Icon( 
            (value) 
            ? Icons.favorite 
            : Icons.favorite_border, 
	      ), 
	      onPressed: playPage.onFavoritePressed, 
	    ); 
      }, 
    ); 
  } 
}

总结

Flutter中的状态管理,可以简单理解为MVVMVM的实现方式。其目的都是为了架起数据和 UI 的桥梁,不同的状态管理方式,本质上是不同的传递数据和事件的方式。

针对不复杂的项目,可以采用service locator的模式,通过GetIt把对应的State Management Layer声明为单例,然后在UI Layer中通过GetIt直接获取。这种模式把项目架构总体分为三层:

  • UI Layer:尽量不要包含逻辑,只负责渲染State的数据;
  • State Management Layer - 响应UI Layer的事件 - 读取Service Layer的数据,处理后传递给UI Layer - 调用Service Layer方法,处理数据 - 把逻辑尽量拆分细,不同模块的逻辑不要混在一起,建议抽取相同模块的逻辑,封装为Notifier,然后在State Management Layer中调用Notifier的实现。
  • Service Layer - 一个项目可能用多个不同的Service - Service定义为interface或者protocol,具体的实现,通过集成自interface的类来实现。

参考

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
FlutterDojo设计之道—状态管理之路(一)
在这个Widget Tree中,通常会存在很多组件之间的相互依赖,时间一长,就很容易变成下面这样。
用户1907613
2020/08/27
1.2K0
Flutter局部刷新三剑客
局部刷新作为提高Flutter页面性能的重要手段,是每一个Flutter老手都必须掌握的技巧。当然,我们不用非得使用Riverpod、Provider、Bloc这些状态管理工具来实现局部刷新,Flutter框架本身也给我们提供了很多方便快捷的刷新方案,今天要提的就是Notifier三剑客,用它来处理局部刷新,代码优雅又方便,可谓是居家必备之良器。
用户1907613
2024/06/27
4250
Flutter局部刷新三剑客
【Flutter 技能篇】你不得不会的状态管理 Provider
本文首发于政采云前端团队博客:【Flutter 技能篇】你不得不会的状态管理 Provider https://www.zoo.team/article/flutter-and-provider
政采云前端团队
2021/01/28
3.9K0
"Fluttr组件ValueListenableBuilder
使用ValueListenableBuilder时需要提供两个 必填参数 :ValueListenable参数和ValueWidgetBuilder 参数。ValueListenable参数用于注册值变化回调。ValueWidgetBuilder用于同步value变化的UI。
徐建国
2021/12/01
2310
"Fluttr组件ValueListenableBuilder
Flutter 的状态管理方案:setState、BLoC、ValueNotifier、Provider
登录页面的主要导航是通过一个小部件实现的,该小部件使用 Drawer 菜单在不同选项中进行选择。
玖柒的小窝
2021/11/28
4.8K0
Flutter 的状态管理方案:setState、BLoC、ValueNotifier、Provider
【Flutter 状态管理】第一论: 对状态管理的看法与理解
状态管理,状态管理。顾名思义是状态+管理,那问题来了,到底什么是状态?为什么要管理呢?
张风捷特烈
2022/03/18
1.7K1
【Flutter 状态管理】第一论: 对状态管理的看法与理解
Flutter漫说:组件生命周期、State状态管理及局部重绘的实现(Inherit)
flutter的生命周期其实有两种:StatefulWidget和StatelessWidget。
BennuCTech
2021/12/10
1.7K0
Flutter漫说:组件生命周期、State状态管理及局部重绘的实现(Inherit)
Flutter入门三部曲(3) - 数据传递/状态管理
这个既熟悉又陌生类可以帮助我们在Flutter中沿着树向下传递信息。这个类只是简单的保存了一个状态而已。
deep_sadness
2018/08/17
1.3K0
Flutter入门三部曲(3) - 数据传递/状态管理
Flutter 组件 | ValueListenableBuilder 局部刷新小能手
我们对初始项目非常熟悉,在 _MyHomePageState 中,通过点击按钮将状态量 _counter 自加,在使用 setState 让当前 State 类持有的 Element 进行更新。作为初学者来说,这很方便,也很容易理解。但对于已入门的人来说,这样的 setState 显然是有失优雅的。
张风捷特烈
2021/01/04
8.5K0
Flutter 组件 |  ValueListenableBuilder 局部刷新小能手
Flutter 对状态管理的认知与思考
这次被捷特大佬催了几次,终于把这篇文章写完了,文章里有我对状态管理的一些思考和看法,希望能引起茫茫人海中零星的共鸣。。。
小呆呆666
2021/09/26
1.2K0
Flutter 知识集锦 | 监听与通知 ChangeNotifier
今天想要和大家好好聊聊 ChangeNotifier 这个东西,从名字上来看它由 change(改变) 和 Notifier(通知器) 构成。打个比方:
张风捷特烈
2023/10/19
1.5K0
Flutter 知识集锦 | 监听与通知 ChangeNotifier
Riverpod - flutter 状态管理的应用
Riverpod 是 Flutter 下知名度较高的状态管理依赖,同样出自 Provider 的开发者 rrousselGit 之手。
xcsoft
2024/07/31
2721
flutter鸿蒙版本mvvm架构思想原理
在Flutter中实现MVVM(Model-View-ViewModel)架构是为了将UI(视图)与业务逻辑(模型和视图模型)分离,提高代码的可维护性和可读性。
淼学派对
2024/10/08
1690
Flutter&鸿蒙next 状态管理高级使用:深入探讨 Provider
在 Flutter 开发中,状态管理是一个至关重要的主题。Flutter 提供了多种状态管理方案,其中 Provider 是最流行和灵活的选择之一。本文将深入探讨 Provider 的高级用法,以帮助开发者更好地理解和应用这一强大的状态管理工具。
淼学派对
2024/11/04
850
flutter鸿蒙版本mvvm架构思想原理
在Flutter中实现MVVM(Model-View-ViewModel)架构是为了将UI(视图)与业务逻辑(模型和视图模型)分离,提高代码的可维护性和可读性。
淼学派对
2024/11/04
1120
Flutter 数据监听Widget
给定ValueListenable 一个泛型和一个构建器,它从泛型的具体值构建小部件,这个类将自动注册为ValueListenable 的侦听器,并在值更改时用更新的值调用构建器。
Flutter笔记
2019/07/24
1.9K0
Flutter 数据监听Widget
重走Flutter状态管理之路—Riverpod进阶篇
前面一篇文章,我们了解了如何正确的去读取状态值,这一篇,我们来了解下不同的Provider都有哪些使用场景。这篇文章,我们将真正的深入了解,如何在不同的场景下,选择合适的种类的Provider,以及这些不同类型的Provider,都有哪些作用。
用户1907613
2022/09/03
4.3K0
重走Flutter状态管理之路—Riverpod进阶篇
2021 年值得期待的 Flutter 数据流管理方案
不像 Redux 在 React 中独占鳌头,Flutter 的数据流管理方案层出不穷,本文旨在介绍在2021年值得使用的 Flutter 数据流管理方案,除了大家都比较熟悉的 InheritedWidget 和 provider, 还有 Remi Rousselet 新推出的、令人十分期待的 Riverpod。希望读者对Flutter 已经有一定的基础,并且了解声明式UI。下面就一起开始吧 1. 什么状态才需要使用数据流管理方案? 对于声明式的 UI 而言,UI = f(state),f 是 build
QQ音乐前端团队
2021/03/29
2.1K0
重走Flutter状态管理之路—Riverpod入门篇
熟悉我的朋友应该都知道,我好几年前写过一个「Flutter状态管理之路」系列,那个时候介绍的是Provider,这也是官方推荐的状态管理工具,但当时没有写完,因为写着写着,觉得有很多地方不尽人意,用着很别扭,所以在写了7篇文章之后,就暂时搁置了。
用户1907613
2022/05/17
3.4K0
Flutter状态管理新的实践
Tech 导读 本文介绍flutter端状态刷新的一种新的思路和尝试,通过dart的扩展属性,定义一个观察者模式,去更新widget的状态,以及如何在widget的生命周期寻找一个切入点,建立订阅关系。
京东技术
2022/09/27
1.1K0
Flutter状态管理新的实践
推荐阅读
相关推荐
FlutterDojo设计之道—状态管理之路(一)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档