flutter bloc 使用详细解析

源码地址
flutter_bloc 是基于 BLoC(Business Logic Component)模式的 Flutter 状态管理库,它封装了 bloc package,帮助我们更清晰地组织业务逻辑与 UI 的分离。核心思想是 事件驱动状态响应


🧠 原理简介

1. 核心概念

  • Event(事件):用户的输入或其他外部触发,比如按钮点击。
  • State(状态):界面状态的表现,比如加载中、成功、失败。
  • Bloc(逻辑组件):接收事件 -> 处理逻辑 -> 发出新状态。

流程图如下:

UI → Bloc.add(Event) → Bloc → emit(State) → UI rebuild

🛠️ 如何使用

1. 安装依赖

dependencies:flutter_bloc: ^8.1.3 # 检查 pub.dev 上的最新版本

2. 创建 Event & State

// counter_event.dart
abstract class CounterEvent {}class Increment extends CounterEvent {}class Decrement extends CounterEvent {}
// counter_state.dart
class CounterState {final int count;CounterState(this.count);
}

3. 创建 Bloc

// counter_bloc.dart
import 'package:flutter_bloc/flutter_bloc.dart';
import 'counter_event.dart';
import 'counter_state.dart';class CounterBloc extends Bloc<CounterEvent, CounterState> {CounterBloc() : super(CounterState(0)) {on<Increment>((event, emit) => emit(CounterState(state.count + 1)));on<Decrement>((event, emit) => emit(CounterState(state.count - 1)));}
}

4. 在 UI 中使用 Bloc

// main.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'counter_bloc.dart';
import 'counter_event.dart';
import 'counter_state.dart';void main() {runApp(MyApp());
}class MyApp extends StatelessWidget {Widget build(BuildContext context) {return BlocProvider(create: (_) => CounterBloc(),child: MaterialApp(home: CounterPage()),);}
}class CounterPage extends StatelessWidget {Widget build(BuildContext context) {final bloc = context.read<CounterBloc>();return Scaffold(appBar: AppBar(title: Text("BLoC Counter")),body: Center(child: BlocBuilder<CounterBloc, CounterState>(builder: (context, state) => Text('Count: ${state.count}', style: TextStyle(fontSize: 30)),),),floatingActionButton: Column(mainAxisAlignment: MainAxisAlignment.end,children: [FloatingActionButton(onPressed: () => bloc.add(Increment()), child: Icon(Icons.add)),SizedBox(height: 10),FloatingActionButton(onPressed: () => bloc.add(Decrement()), child: Icon(Icons.remove)),],),);}
}

✅ 总结优点

  • UI 和业务逻辑分离,利于测试和维护
  • 明确的事件-状态流转,代码可读性强
  • 强类型 + 自动重建 UI,适用于中大型项目

和 getx 相比有什么优缺点

flutter_blocGetX 是 Flutter 中两种常见的状态管理方案,各有优缺点,适用于不同的场景。下面是二者的详细对比:


🆚 flutter_bloc vs GetX

维度flutter_blocGetX
设计思想响应式 + 明确事件流转(事件 -> 状态)响应式 + 最小 API(简洁直接)
代码结构规范、结构清晰(Event / State / Bloc)极简、灵活(Controller + Observable)
学习曲线中等偏陡,概念较多非常简单,上手极快
样板代码(boilerplate)多,需要定义多个类极少,一个控制器基本搞定
可维护性(大型项目)高,适合多人协作和规范化开发灵活但风险高,依赖命名和使用习惯
社区和文档强,广泛用于企业项目,如 Google 官方推荐非官方但很流行,文档充足
依赖注入(DI)不强制内置,可配合其他包(如 get_it内置自动依赖注入
导航/路由管理依赖其他包(如 go_router自带强大的路由系统
性能非常高效,基于 Streamemit极高,Reactive 系统 + 最小重建
测试友好性强,适合单元测试/集成测试一般,较多手动控制
异步处理基于事件流程,清晰且易测试支持 Future/async,但自由度高可能导致不规范

✅ 何时选 flutter_bloc

适合你如果:

  • 需要严格分离业务逻辑(企业/团队协作项目)
  • 希望状态流转可追踪、可测试
  • 项目规模较大或可预期扩展
  • 你熟悉 Redux / Rx 风格编程

✅ 何时选 GetX

适合你如果:

  • 项目较小或是个人开发
  • 优先快速开发、上手快
  • 喜欢灵活、少写代码
  • 同时希望统一路由/DI/状态/国际化等功能

🏁 举例对比:计数器

Bloc 实现

bloc.add(Increment()); 
// 多个文件:event.dart, state.dart, bloc.dart

GetX 实现

controller.count++;
// 只要一个 Controller 类,UI 使用 Obx 自动监听

📌 总结一句话:

Bloc 注重规范和可维护性,适合大型工程;GetX 注重极简和开发效率,适合快速开发。

BuildContext 上的一些扩展方法

在使用 flutter_bloc(或 provider)时,BuildContext 上的一些扩展方法是关键,它们帮助你从上下文中访问 Bloc、监听状态、或者进行条件性重建。

以下是常见的几种方法的详细解释和对比:


✅ 1. context.read<T>()

功能:

  • 从 widget tree 中 读取 一个 Bloc(或其他 Provider 提供的对象),不会监听其状态变化

用途:

  • 通常用于触发事件,如 .add(Event),因为不需要监听。

示例:

context.read<CounterBloc>().add(Increment());

✅ 2. context.watch<T>()

功能:

  • 读取并订阅监听 Bloc 或状态变化。
  • 状态变化会导致 widget rebuild

用途:

  • 通常用于 UI 需要根据 Bloc 状态实时刷新。

示例:

final state = context.watch<CounterBloc>().state;
return Text('Count: ${state.count}');

✅ 3. context.select<T, R>(R Function(T value))

功能:

  • 读取 Bloc(或 Provider)中某个字段的值,并监听它的变化。
  • 只有当该字段的值发生变化时,才会触发 rebuild

用途:

  • 精细控制重建,避免无谓的 UI 更新

示例:

final count = context.select<CounterBloc, int>((bloc) => bloc.state.count);
return Text('Count: $count');

✅ 4. BlocProvider.of<T>(context)

  • 等价于 context.read<T>()
  • 是旧写法,推荐使用 context.read<T>() 更简洁。

✅ 5. BlocBuilder<T, S>

功能:

  • 监听 Bloc<T> 的状态 S 并根据状态变化 rebuild UI。

示例:

BlocBuilder<CounterBloc, CounterState>(builder: (context, state) => Text('Count: ${state.count}'),
);

✅ 6. BlocListener<T, S>

功能:

  • 用于监听状态变化并做一次性副作用操作(如弹窗、跳转)。

示例:

BlocListener<LoginBloc, LoginState>(listener: (context, state) {if (state is LoginSuccess) {Navigator.pushNamed(context, '/home');}},child: ...
);

✅ 7. BlocConsumer<T, S>

  • 相当于 BlocBuilder + BlocListener 的组合。
  • 同时用于 build UI 和执行副作用。

🔁 方法使用场景对比表

方法名是否 rebuild是否监听状态变化用途
read<T>()获取 Bloc 实例、添加事件
watch<T>()获取 Bloc 状态,状态变就重建
select<T, R>()✅ (条件)✅ (某字段变)精细控制重建,提高性能
BlocBuilder渲染 UI
BlocListener处理一次性副作用
BlocConsumerUI 和副作用一起处理

使用场景举例子

好的,我们用一个异步 API 请求的完整例子来演示 flutter_bloc 中各类常用方法的实际应用,包括:

  • context.read
  • context.watch
  • context.select
  • BlocBuilder
  • BlocListener
  • BlocConsumer

🌐 场景描述:请求用户信息

模拟从网络请求一个用户信息(名字、邮箱),展示加载中、成功、失败三种状态。


📦 第一步:定义状态和事件

// user_event.dart
abstract class UserEvent {}class FetchUser extends UserEvent {}
// user_state.dart
abstract class UserState {}class UserInitial extends UserState {}class UserLoading extends UserState {}class UserLoaded extends UserState {final String name;final String email;UserLoaded({required this.name, required this.email});
}class UserError extends UserState {final String message;UserError(this.message);
}

⚙️ 第二步:创建 UserBloc

// user_bloc.dart
import 'package:flutter_bloc/flutter_bloc.dart';
import 'user_event.dart';
import 'user_state.dart';class UserBloc extends Bloc<UserEvent, UserState> {UserBloc() : super(UserInitial()) {on<FetchUser>((event, emit) async {emit(UserLoading());await Future.delayed(Duration(seconds: 2)); // 模拟网络延迟try {// 模拟 API 成功返回final name = 'Alice';final email = 'alice@example.com';emit(UserLoaded(name: name, email: email));} catch (e) {emit(UserError('Failed to fetch user'));}});}
}

🖼️ 第三步:UI 中使用 Bloc

// user_page.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'user_bloc.dart';
import 'user_event.dart';
import 'user_state.dart';class UserPage extends StatelessWidget {Widget build(BuildContext context) {return BlocProvider(create: (_) => UserBloc(),child: UserView(),);}
}class UserView extends StatelessWidget {Widget build(BuildContext context) {final bloc = context.read<UserBloc>(); // 获取 Bloc 实例return Scaffold(appBar: AppBar(title: Text('User Info')),body: BlocConsumer<UserBloc, UserState>(listener: (context, state) {if (state is UserError) {ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(state.message)),);}},builder: (context, state) {if (state is UserInitial) {return Center(child: ElevatedButton(onPressed: () => bloc.add(FetchUser()),child: Text('Load User'),),);} else if (state is UserLoading) {return Center(child: CircularProgressIndicator());} else if (state is UserLoaded) {return Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Text('Name: ${state.name}'),Text('Email: ${state.email}'),],),);} else {return Center(child: Text('Unknown state'));}},),);}
}

🧠 其他方法用法补充

context.watch 示例(只监听状态)

final userState = context.watch<UserBloc>().state;
if (userState is UserLoaded) {print(userState.name);
}

context.select 示例(只监听 name 变化)

final name = context.select<UserBloc, String?>((bloc) {final state = bloc.state;return state is UserLoaded ? state.name : null;
});

✅ 总结

这个例子完整地展示了:

  • 如何使用 Bloc 组织异步逻辑
  • 如何使用 context.read 触发事件
  • 如何用 BlocConsumer 分离 UI 构建和副作用(如错误提示)
  • 如何用 watch / select 实现更细粒度监听

## 标题RepositoryProvider

RepositoryProviderflutter_bloc 提供的一个工具类,作用是将“非 Bloc 的对象(如 Repository、Service、API 客户端)注入到 widget tree 中”,供 Bloc 或其他组件使用。它本质上是一个语义化的 Provider,目的是让依赖注入更加清晰和语义化。


🧱 1. RepositoryProvider 是什么?

它是 Provider 的语法糖,用于提供数据访问层(Repository),让 Bloc 通过依赖注入获取它。

RepositoryProvider(create: (context) => UserRepository(),child: BlocProvider(create: (context) => UserBloc(context.read<UserRepository>()),child: MyApp(),),
)

🧩 2. 为什么需要 RepositoryProvider?

分离关注点 + 提高可测试性

在 BLoC 架构中,Bloc 只处理业务逻辑,而 Repository 专注于数据来源(数据库/API/本地缓存等)。

  • 🧼 清晰的依赖层次结构
  • 🔌 可插拔(方便 mock 测试)
  • ♻️ 依赖共享(避免重复创建对象)

🧪 3. 实战示例

用户仓库

class UserRepository {Future<String> fetchUserName() async {await Future.delayed(Duration(seconds: 1));return 'Alice';}
}

注入层级

void main() {runApp(RepositoryProvider(create: (context) => UserRepository(),child: BlocProvider(create: (context) => UserBloc(context.read<UserRepository>()),child: MyApp(),),),);
}

在 Bloc 中使用

class UserBloc extends Bloc<UserEvent, UserState> {final UserRepository userRepository;UserBloc(this.userRepository) : super(UserInitial()) {on<FetchUser>((event, emit) async {emit(UserLoading());final name = await userRepository.fetchUserName();emit(UserLoaded(name));});}
}

✅ 4. 优点总结

优点说明
👓 语义清晰明确指出这是 Repository,不是 Bloc
♻️ 对象共享上层创建、下层 Bloc 可复用
🧪 易测试Bloc 接收参数,可以注入 mock
🧩 解耦结构Bloc 不负责创建数据层

⚠️ 5. 注意事项 / 潜在缺点

缺点或注意点说明
⚠️ 滥用嵌套BlocProvider 和 RepositoryProvider 层级深容易混乱,建议封装为模块
⚠️ 生命周期问题如果作用域太小,Bloc 中引用的 Repository 可能会被提前销毁
⚠️ 多仓库依赖复杂度提升Bloc 依赖多个 Repository 时,构造函数会变长,可考虑封装为 Service 层或使用 DI 工具(如 get_it)

📌 何时使用 RepositoryProvider?

✅ 使用场景:

  • 需要复用或共享 Repository 实例(如网络请求、数据库访问)
  • Bloc 不应该直接创建依赖对象
  • 需要单元测试 Bloc 时方便注入 mock

❌ 不建议使用场景:

  • 简单小项目可以直接在 Bloc 中创建对象(仅限临时用)
  • 对象生命周期不需要跨多个组件

一个多仓库 + 多 Bloc 的组合使用场景实例

好的,我们来构建一个中型项目的多仓库 + 多 Bloc + 多 Provider 示例结构,结合 RepositoryProviderBlocProvider,实现高内聚、低耦合的结构设计。


🧱 示例需求:用户信息 + 设置模块

有两个功能模块:

  1. 用户模块(User):从 API 获取用户信息
  2. 设置模块(Settings):管理本地配置(如暗黑模式)

模块依赖:

模块依赖内容
UserBloc依赖 UserRepository
SettingsBloc依赖 SettingsRepository

📦 项目结构建议

lib/
├── main.dart
├── repositories/
│   ├── user_repository.dart
│   └── settings_repository.dart
├── blocs/
│   ├── user/
│   │   ├── user_bloc.dart
│   │   ├── user_event.dart
│   │   └── user_state.dart
│   └── settings/
│       ├── settings_bloc.dart
│       ├── settings_event.dart
│       └── settings_state.dart
├── pages/
│   ├── user_page.dart
│   └── settings_page.dart
└── app.dart

1️⃣ Repository 实现

user_repository.dart

class UserRepository {Future<String> fetchUserName() async {await Future.delayed(Duration(seconds: 1));return 'Alice';}
}

settings_repository.dart

class SettingsRepository {bool _darkMode = false;bool get isDarkMode => _darkMode;void toggleDarkMode() => _darkMode = !_darkMode;
}

2️⃣ Bloc 实现(以 User 为例)

user_bloc.dart

class UserBloc extends Bloc<UserEvent, UserState> {final UserRepository userRepository;UserBloc(this.userRepository) : super(UserInitial()) {on<FetchUser>((event, emit) async {emit(UserLoading());final name = await userRepository.fetchUserName();emit(UserLoaded(name));});}
}

3️⃣ 组合使用(main.dart)

void main() {runApp(MultiRepositoryProvider(providers: [RepositoryProvider(create: (_) => UserRepository()),RepositoryProvider(create: (_) => SettingsRepository()),],child: MultiBlocProvider(providers: [BlocProvider(create: (context) => UserBloc(context.read<UserRepository>()),),BlocProvider(create: (context) => SettingsBloc(context.read<SettingsRepository>()),),],child: MyApp(),),),);
}

4️⃣ 页面中使用

user_page.dart

class UserPage extends StatelessWidget {Widget build(BuildContext context) {return BlocBuilder<UserBloc, UserState>(builder: (context, state) {if (state is UserInitial) {return ElevatedButton(onPressed: () => context.read<UserBloc>().add(FetchUser()),child: Text("Load User"),);} else if (state is UserLoaded) {return Text('Hello, ${state.name}');} else {return CircularProgressIndicator();}},);}
}

settings_page.dart

class SettingsPage extends StatelessWidget {Widget build(BuildContext context) {return BlocBuilder<SettingsBloc, SettingsState>(builder: (context, state) {return SwitchListTile(title: Text('Dark Mode'),value: state.isDarkMode,onChanged: (_) => context.read<SettingsBloc>().add(ToggleTheme()),);},);}
}

✅ 优点总结

  • 清晰的依赖注入结构:Bloc 和 Repository 解耦,易维护
  • 复用性强:多个 Bloc 可共用同一个 Repository 实例
  • 测试友好:可轻松 mock Repository 进行单元测试
  • 清晰语义:RepositoryProvider 表明它不是 Bloc,而是数据提供者

🚀 Bonus:封装更进一步

✅ 已经成功将 MultiRepositoryProviderMultiBlocProvider 封装到了 AppProviderWrapper 组件中,结构清晰、职责分离得非常好!

下面是总结和优化建议:


✅ 目前结构回顾

// main.dart
runApp(AppProviderWrapper(child: MyApp()));
// provider_wrapper.dart
class AppProviderWrapper extends StatelessWidget {final Widget child;const AppProviderWrapper({required this.child});...
}

这非常适合中大型项目,可以让 main.dart 逻辑更纯粹,同时也方便后续扩展全局错误监听、日志注入等中间件。


💡 可选优化建议

1. 使用 lazy: false 控制立即初始化 Bloc

有些 Bloc(如 SettingsBloc)可能希望 App 启动时就立即初始化:

BlocProvider(lazy: false,create: (context) => SettingsBloc(context.read<SettingsRepository>()),
),
2. 使用 const 构造节省 rebuild

如果子 Widget 和 Bloc 无关,记得加 const 以避免重建。

3. 模块化进一步优化(可选)

可以把 Bloc、Repository 的创建封装成方法,增强可维护性:

List<RepositoryProvider> buildRepositories() => [RepositoryProvider(create: (_) => UserRepository()),RepositoryProvider(create: (_) => SettingsRepository()),
];List<BlocProvider> buildBlocs(BuildContext context) => [BlocProvider(create: (_) => UserBloc(context.read())),BlocProvider(create: (_) => SettingsBloc(context.read())),
];

这样 AppProviderWrapper 中就可以这么写:

child: MultiBlocProvider(providers: buildBlocs(context),child: child,
),

✅ 总结

现在的结构已经非常标准、清晰,完全符合企业级 Flutter 项目推荐架构。
源码地址

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/87780.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/87780.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c++ 语言在无人机应用开发中的应用

C 语言在无人机应用开发中扮演着核心角色&#xff0c;特别是在对性能、实时性、资源利用效率和底层硬件控制有严格要求的领域。以下是其主要应用领域&#xff1a; 飞控系统 (Flight Control System - FCS) 核心功能&#xff1a; 这是无人机的大脑。C 用于实现核心的导航、制导与…

Uniapp本地存储(uni.setStorage)全面解析与实践指南

在移动应用开发中&#xff0c;本地存储是不可或缺的核心功能之一。作为跨平台开发框架&#xff0c;Uniapp提供了一套完善的本地存储解决方案&#xff0c;使开发者能够轻松实现数据的持久化存储。本文将深入探讨Uniapp本地存储的方方面面&#xff0c;从基础使用到高级技巧&#…

n8n教程:5分钟部署+自动生AI日报并写入飞书多维表格

哈喽&#xff0c;大家好&#x1f44f; 我是阿星&#xff01; 最近n8n太火了。什么是n8n&#xff1f;有点像扣子和dify的综合体。 简单来说就是替你打工的「自动化工作流」 我们今天就从部署&#x1f449;搭建第一个工作流。用它实现自动抓取新闻并分类。 教程有点长&#x…

禾纳 AET3152AP 电源MOS IC完全替代TDM3307 替代TDM2307泰德电子料 国产芯片

禾纳半导体的电源管理芯片AET3152AP不含卤素和锑&#xff0c;符合Rohs标准&#xff0c;应用在交换机切换&#xff0c;便携式/台式机中的电源管理等&#xff0c;可pin to pin替代TDM3307或TDM2307. AET3152AP 封装为PDFN3030 &#xff0c;最小包装数为5000pcs AET3152AP工作温…

专题:2025信创产业新发展+AI趋势数字化研究报告|附30+份报告PDF汇总下载

原文链接&#xff1a;https://tecdat.cn/?p42711 本报告汇总解读聚焦信创产业核心发展脉络&#xff0c;以数据驱动视角剖析技术演进与市场变革。信创产业作为国家数字安全与技术自主可控的核心载体&#xff0c;正经历从“可用”到“好用”的关键跃迁。 本报告洞察基于《亿欧智…

电子电气架构 --- 分区电子电气架构如何支持软件定义汽车

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…

【简单】344.反转字符串

题目描述 编写一个函数&#xff0c;其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。 不要给另外的数组分配额外的空间&#xff0c;你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。 示例 1&#xff1a; 输入&#xff1a;s ["h&quo…

CVE-2025-24813源码分析与漏洞复现(Tomcat 路径等效漏洞与反序列化RCE)

漏洞概述 漏洞名称&#xff1a;Tomcat 路径等效漏洞反序列化远程代码执行&#xff08;RCE&#xff09; CVE 编号&#xff1a;CVE-2025-24813 CVSS 评分&#xff1a;9.8 影响版本&#xff1a; 9.0.0.M1 ≤ Tomcat ≤ 9.0.9810.1.0-M1 ≤ Tomcat ≤ 10.1.3411.0.0-M1 ≤ Tomcat…

深入解析:如何实时获取Socket接收缓冲区的数据量

在网络编程中&#xff0c;精确掌握接收缓冲区的数据状态是优化性能的关键。本文将揭秘如何跨平台获取socket接收缓冲区的可读数据量&#xff0c;并分析实际应用中的注意事项。 一、核心API&#xff1a;操作系统级数据探针 1. Windows平台方案 #include <winsock2.h>// …

Edge卸载应用

Edge安装应用后&#xff0c;出现在开始菜单&#xff0c;不能卸载。

Cursor Rules 的核心定位与作用

Cursor Rules 是 AI 编程工具 Cursor IDE 中的核心功能&#xff0c;用于约束 AI 生成代码的行为&#xff0c;确保其符合项目规范、编码风格或特定技术需求。它本质上是一套持久化、可复用的指令集&#xff0c;会动态插入到 AI 模型的上下文提示中&#xff0c;指导其生成代码的逻…

多线程爬虫优化:快速爬取并写入CSV

在数据驱动的时代&#xff0c;爬虫技术已成为获取网络数据的重要手段。然而&#xff0c;随着数据量的不断增加&#xff0c;单线程爬虫的效率逐渐难以满足需求。多线程爬虫通过并行处理&#xff0c;能够显著提升爬取速度&#xff0c;同时将数据快速写入CSV文件&#xff0c;为后续…

Deepseek+墨刀,1min快速生成流程图!

想要了解快速了解产品逻辑&#xff0c;可以用ds墨刀快速生成流程图~ deepseek链接&#xff1a;https://www.deepseek.com/ 墨刀在线&#xff1a;https://modao.cc/brand 如何操作呢&#xff1f; 1.打开deepseek&#xff0c;输入以下咒语&#xff0c;让AI用Mermaid语法绘制流…

LangChain4j流式调用、消息注解与会话记忆

我们先用AiService工具类把调用ai大语言模型的代码写出来。因为AiService工具类中整合有记忆、Rag知识库、tools工具等&#xff0c;我们直接配置调用即可。 我用的是qwen-plus模型。 引入依赖&#xff1a; <dependency><groupId>dev.langchain4j</groupId>…

NtfsWriteLog函数分析之OpenAttributeTableDump

第一部分&#xff1a; NtfsWriteLog( IrpContext, Vcb->MftScb, //注意&#xff1a;Vcb->MftScb NULL, OpenAttributeTableDump, …

DCM4CHEE ARCHIVE LIGHT 源代码解析(2)-STOWRS

系列文章目录 DCM4CHEE ARCHIVE LIGHT 源代码解析(1)-前言DCM4CHEE ARCHIVE LIGHT 源代码解析(2)-STOWRS文章目录 系列文章目录概述一、背景资料1、RESTful服务2、传输存储规范3、服务连接策略4、响应消息状态二、业务分析1、对象关系2、项目结构3、业务流程三、代码解析1、w…

Java中间件简介:构建现代软件的“隐形桥梁”

Java中间件简介&#xff1a;构建现代软件的“隐形桥梁” 在软件开发的世界里&#xff0c;中间件&#xff08;Middleware&#xff09;是一个既熟悉又神秘的存在。它不像数据库那样直接存储数据&#xff0c;也不像前端那样与用户交互&#xff0c;但它却是现代软件架构中不可或缺…

Scale AI 的王晓磊带着对整个 AI 行业动态的深入了解加入 Meta

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

冒烟测试概念速解

最近很多人对冒烟测试这个概念发出疑问。那么我就来简单解释一下什么是冒烟测试&#xff0c;以及冒烟测试的由来。 1.冒烟测试的由来 硬件测试的起源&#xff1a;从 “冒烟” 到基础功能验证 在电子工程领域&#xff0c;早期工程师在调试新硬件&#xff08;如电路板、芯片&am…

嵌入式学习笔记——day36-多路IO复用

一、基本概念 &#xff08;服务器多客户端模型&#xff09; 定义&#xff1a; 单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用&#xff1a; 应用程序通常需要处理来自多条事件流中的事件&#xff0c;比如我现在用的电脑&#xff0c;需要同时处理键盘鼠…