Flutter鸿蒙next 使用 BLoC 模式进行状态管理详解
1. 引言
在 Flutter 中,随着应用规模的扩大,管理应用中的状态变得越来越复杂。为了处理这种复杂性,许多开发者选择使用不同的状态管理方案。其中,BLoC(Business Logic Component)模式作为一种流行的状态管理方法,因其将应用的业务逻辑与 UI 层分离而广泛应用。
本文将详细介绍如何在 Flutter 中使用 BLoC 模式进行状态管理,涵盖基本概念、实现步骤及代码示例,同时进行深入的代码解释,帮助开发者理解这一模式的精髓。
2. 什么是 BLoC 模式?
BLoC 是一种将业务逻辑从 UI 层分离的模式。它基于 Streams(流)和 Sinks(输入)的概念,将状态管理和 UI 更新通过流式的方式来实现。通过这种方式,UI 层通过监听数据流(Stream)来获取状态更新,避免了状态直接与 UI 层耦合,提高了代码的可维护性和可测试性。
核心组件:
- Event:用户或系统触发的事件,代表一种动作或请求。
- State:UI 显示的当前状态,通常是数据的一个集合。
- Bloc:接收事件并转换为状态的核心业务逻辑组件。
Bloc 模式的核心原则就是 通过事件驱动状态的更新,并且 UI 层只关心状态的变化,而不关心事件的处理过程。
3. 使用 BLoC 的流程
使用 BLoC 模式的基本流程大致如下:
- 创建 Event 和 State 类:首先,定义一些 Event 和 State 类。
- 创建 Bloc 类:Bloc 类用于处理事件和状态之间的映射。
- 提供 Bloc:在 UI 中通过
BlocProvider提供 Bloc 实例,确保其生命周期的管理。 - 通过 BlocBuilder 或 BlocListener 更新 UI:UI 通过监听状态变化来更新界面。
4. 代码示例
接下来,创建一个简单的计数器应用,通过 BLoC 模式管理计数器的增减操作。
代码结构:
CounterEvent:定义可能的用户操作事件。CounterState:定义计数器的状态。CounterBloc:处理事件并输出状态。
代码实现:
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';// 1. 定义 Event
abstract class CounterEvent {}class IncrementEvent extends CounterEvent {}class DecrementEvent extends CounterEvent {}// 2. 定义 State
class CounterState {final int counter;CounterState({required this.counter});
}// 3. 定义 Bloc
class CounterBloc extends Bloc<CounterEvent, CounterState> {CounterBloc() : super(CounterState(counter: 0));@overrideStream<CounterState> mapEventToState(CounterEvent event) async* {if (event is IncrementEvent) {yield CounterState(counter: state.counter + 1);} else if (event is DecrementEvent) {yield CounterState(counter: state.counter - 1);}}
}// 4. 主程序界面
void main() {runApp(MyApp());
}class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(home: BlocProvider(create: (context) => CounterBloc(),child: CounterPage(),),);}
}class CounterPage extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('BLoC Counter')),body: Center(child: BlocBuilder<CounterBloc, CounterState>(builder: (context, state) {return Column(mainAxisAlignment: MainAxisAlignment.center,children: [Text('Counter Value: ${state.counter}', style: TextStyle(fontSize: 30)),Row(mainAxisAlignment: MainAxisAlignment.center,children: [ElevatedButton(onPressed: () => context.read<CounterBloc>().add(IncrementEvent()),child: Text('Increment'),),SizedBox(width: 10),ElevatedButton(onPressed: () => context.read<CounterBloc>().add(DecrementEvent()),child: Text('Decrement'),),],)],);},),),);}
}
5. 代码详细解释
1. 定义 Event 类
abstract class CounterEvent {}
class IncrementEvent extends CounterEvent {}
class DecrementEvent extends CounterEvent {}
CounterEvent 是一个抽象类,所有事件类型都继承自该类。我们定义了两个具体的事件:IncrementEvent 和 DecrementEvent,分别表示计数器增加和减少。
2. 定义 State 类
class CounterState {final int counter;CounterState({required this.counter});
}
CounterState 用于表示计数器的状态,包含一个名为 counter 的整数变量,表示当前计数值。State 负责存储应用的状态,它是 BLoC 模式的核心。
3. 定义 Bloc 类
class CounterBloc extends Bloc<CounterEvent, CounterState> {CounterBloc() : super(CounterState(counter: 0));@overrideStream<CounterState> mapEventToState(CounterEvent event) async* {if (event is IncrementEvent) {yield CounterState(counter: state.counter + 1);} else if (event is DecrementEvent) {yield CounterState(counter: state.counter - 1);}}
}
CounterBloc 是处理业务逻辑的核心部分,继承自 Bloc<CounterEvent, CounterState>。在构造函数中,我们初始化了计数器状态为 0。mapEventToState 方法用于处理事件并将状态转换为新的状态。例如,当接收到 IncrementEvent 时,计数器的值加 1,并通过 yield 关键字返回一个新的 CounterState。
4. 提供 Bloc 并更新 UI
class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(home: BlocProvider(create: (context) => CounterBloc(),child: CounterPage(),),);}
}
BlocProvider 用于提供 CounterBloc 实例,确保它在 widget 树中是可访问的。在这里,我们将 CounterBloc 提供给 CounterPage 进行状态管理。
BlocBuilder<CounterBloc, CounterState>(builder: (context, state) {return Column(children: [Text('Counter Value: ${state.counter}'),Row(children: [ElevatedButton(onPressed: () => context.read<CounterBloc>().add(IncrementEvent()),child: Text('Increment'),),ElevatedButton(onPressed: () => context.read<CounterBloc>().add(DecrementEvent()),child: Text('Decrement'),),],),],);},
)
BlocBuilder 监听 CounterBloc 输出的 CounterState,并根据 state 更新 UI。点击按钮时,通过 context.read<CounterBloc>().add() 来触发相应的事件,从而更新计数器的状态。
6. 总结
通过 BLoC 模式,我们成功将业务逻辑从 UI 层分离,使得应用的状态管理更加清晰、可维护。BLoC 模式的核心思想是通过事件驱动状态的变化,UI 只需要关注状态的变化,而不需要直接操作状态或事件,降低了组件之间的耦合性。
这种模式特别适合于需要管理大量复杂状态的应用,例如社交媒体、新闻应用等,通过合理的事件与状态划分,可以实现高效的 UI 更新和良好的代码结构。
相关文章:
Flutter鸿蒙next 使用 BLoC 模式进行状态管理详解
1. 引言 在 Flutter 中,随着应用规模的扩大,管理应用中的状态变得越来越复杂。为了处理这种复杂性,许多开发者选择使用不同的状态管理方案。其中,BLoC(Business Logic Component)模式作为一种流行的状态管…...
Gen-RecSys——一个通过生成和大规模语言模型发展起来的推荐系统
概述 生成模型的进步对推荐系统的发展产生了重大影响。传统的推荐系统是 “狭隘的专家”,只能捕捉特定领域内的用户偏好和项目特征,而现在生成模型增强了这些系统的功能,据报道,其性能优于传统方法。这些模型为推荐的概念和实施带…...
Android 重新定义一个广播修改系统时间,避免系统时间混乱
有时候,搞不懂为什么手机设备无法准确定义系统时间,出现混乱或显示与实际不符,需要重置或重新设定一次才行,也是真的够无语的!! vendor/mediatek/proprietary/packages/apps/MtkSettings/AndroidManifest.…...
第3章:角色扮演提示-Claude应用开发教程
更多教程,请访问claude应用开发教程 设置 运行以下设置单元以加载您的 API 密钥并建立 get_completion 辅助函数。 !pip install anthropic# Import pythons built-in regular expression library import re import anthropic# Retrieve the API_KEY & MODEL…...
【FAQ】HarmonyOS SDK 闭源开放能力 —Vision Kit
1.问题描述: 人脸活体检测页面会有声音提示,如何控制声音开关? 解决方案: 活体检测暂无声音控制开关,但可通过其他能力控制系统音量,从而控制音量。 活体检测页面固定音频流设置的是8(无障碍…...
【问题解决】Tomcat由低于8版本升级到高版本使用Tomcat自带连接池报错无法找到表空间的问题
问题复现 项目上历史项目为解决漏洞扫描从Tomcat 6.0升级到了9.0版本,服务启动的日志显示如下警告,数据源是通过JNDI方式在server.xml中配置的,控制台上狂刷无法找到表空间的错误(没截图) 报错: 06-Nov-…...
Git LFS
Git LFS(Git Large File Storage)是一个用于管理和版本控制大文件的工具,它扩展了 Git 的功能,帮助处理大文件或二进制文件的存储和管理问题。 为什么需要 Git LFS? Git 默认是针对文本文件进行优化的,尤…...
基于Redis缓存机制实现高并发接口调试
创建接口 这里使用的是阿里云提供的接口服务直接做的测试,接口地址 curl http://localhost:8080/initData?tokenAppWithRedis 这里主要通过参数cacheFirstfalse和true来区分是否走缓存,正常的业务机制可能是通过后台代码逻辑自行控制的,这…...
数字化转型实践:金蝶云星空与钉钉集成提升企业运营效率
数字化转型实践:金蝶云星空与钉钉集成提升企业运营效率 本文介绍了深圳一家电子设备制造企业在数字化转型过程中,如何通过金蝶云星空与钉钉的高效集成应对挑战、实施解决方案,并取得显著成果。集成项目在提高沟通效率、自动化审批流程和监控异…...
Flutter 鸿蒙next 中使用 MobX 进行状态管理
Flutter & 鸿蒙next 中使用 MobX 进行状态管理 在应用开发中,状态管理是一个至关重要的环节,特别是在复杂的Flutter或鸿蒙next项目中。状态的变化往往会影响UI的更新,因此,选择一种高效、灵活的状态管理工具显得尤为重要。Mo…...
1.62亿元!812个项目立项!上海市2024年度“科技创新行动计划”自然科学基金项目立项
本期精选SCI&EI ●IEEE 1区TOP 计算机类(含CCF); ●EI快刊:最快1周录用! 知网(CNKI)、谷歌学术期刊 ●7天录用-检索(100%录用),1周上线; 免费稿件评估 免费匹配期…...
Redis数据库测试和缓存穿透、雪崩、击穿
Redis数据库测试实验 实验要求 1.新建一张user表,在表内插入10000条数据。 2.①通过jdbc查询这10000条数据,记录查询时间。 ②通过redis查询这10000条数据,记录查询时间。 3.①再次查询这一万条数据,要求根据年龄进行排序&#…...
[vulnhub] DarkHole: 2
https://www.vulnhub.com/entry/darkhole-2,740/ 端口扫描主机发现 探测存活主机,185是靶机 # nmap -sP 192.168.75.0/24 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-11-08 18:02 CST Nmap scan report for 192.168.75.1 Host is up (0.…...
《XGBoost算法的原理推导》12-2 t轮迭代中对样本i的预测值 公式解析
本文是将文章《XGBoost算法的原理推导》中的公式单独拿出来做一个详细的解析,便于初学者更好的理解。 好的,公式(12-2)表示的是 XGBoost 在第 t t t 轮迭代中对样本 i i i 的预测值。它说明了在第 t t t 轮迭代中,模型的预测是通过累加之前…...
./bin/mindieservice_daemon启动成功
接MindIE大模型测试及报错Fatal Python error: PyThreadState_Get: the function must be called with the GIL held,-CSDN博客经过调整如下红色部分参数,昇腾310P3跑起来了7b模型: rootdev-8242526b-01f2-4a54-b89d-f6d9c57c692d-qjhpf:/home/apulis-de…...
Linux: network: ip link M-DOWN的具体含义是什么?
文章目录 参考简介实例代码解释openstack上的显示如果是在一个interface上建立了vlan参考 https://unix.stackexchange.com/questions/348327/using-ip-what-does-m-down-mean www.policyrouting.org/iproute2.doc.html#ss9.1 简介 是指上一级的接口的状态。 实例 4: ersp…...
Spring中的过滤器和拦截器
Spring中的过滤器和拦截器 一、引言 在Spring框架中,过滤器(Filter)和拦截器(Interceptor)是实现请求处理的两种重要机制。它们都基于AOP(面向切面编程)思想,用于在请求的生命周期…...
leetcode20.括号匹配
题目描述 给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。 有效字符串需满足: 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 每个…...
Unity性能优化-具体操作
批量渲染是通过减少CPU向GPU发送渲染命令(DrawCall)的次数,以及减少GPU切换渲染状态的次数,尽量让GPU一次多做一些事情,来提升逻辑线和渲染线的整体效率。 Draw Call性能消耗原因是命令从Runtime到Driver的过程中&…...
【嵌入式开发——ARM】1ARM架构
嵌入式领域,使用ARM架构的芯片公司可不占少数吧,intel的x86架构主要占据PC、服务器市场,ARM架构主要占据移动市场。x86架构和ARM架构不同的主要原因,是背后使用的计算机指令集不同。计算机有自己的语言系统(汇编&#…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
Xela矩阵三轴触觉传感器的工作原理解析与应用场景
Xela矩阵三轴触觉传感器通过先进技术模拟人类触觉感知,帮助设备实现精确的力测量与位移监测。其核心功能基于磁性三维力测量与空间位移测量,能够捕捉多维触觉信息。该传感器的设计不仅提升了触觉感知的精度,还为机器人、医疗设备和制造业的智…...
LUA+Reids实现库存秒杀预扣减 记录流水 以及自己的思考
目录 lua脚本 记录流水 记录流水的作用 流水什么时候删除 我们在做库存扣减的时候,显示基于Lua脚本和Redis实现的预扣减 这样可以在秒杀扣减的时候保证操作的原子性和高效性 lua脚本 // ... 已有代码 ...Overridepublic InventoryResponse decrease(Inventor…...
【java】【服务器】线程上下文丢失 是指什么
目录 ■前言 ■正文开始 线程上下文的核心组成部分 为什么会出现上下文丢失? 直观示例说明 为什么上下文如此重要? 解决上下文丢失的关键 总结 ■如果我想在servlet中使用线程,代码应该如何实现 推荐方案:使用 ManagedE…...
