mcpField
F
flutter-bloc

flutter-bloc

github.com/dhruvanbhalara开发30255 次安装8 周前更新
代码仓库

关于 flutter-bloc

面向 Flutter 开发者的 BLoC 状态管理规范,涵盖不可变事件与状态、异步流程、UI 职责、依赖注入和路由约定。

主要功能

  1. 01使用密封且不可变的事件与状态
  2. 02异步流程先加载再返回结果
  3. 03提供 BLoC 组件使用规范
  4. 04规定依赖注入方式
  5. 05规范路由与 Provider
  6. 06按功能组织目录结构

适用场景

  1. 01启动 Flutter BLoC 功能开发
  2. 02检查异步状态转换
  3. 03分离 UI 与业务逻辑
  4. 04组织路由和 BLoC Provider

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/dhruvanbhalara/skills --skill flutter-bloc

安装后在 Claude Code 中输入/flutter-bloc确认已加载。

详细介绍

BLoC 模式

  • 密封状态与事件:状态和事件都必须使用 sealed class,以确保 UI 处理完整,并在编译时保证安全。
  • 不可变性:所有状态、事件和领域实体都必须不可变(使用 final 和 Equatable 或 freezed)。
  • 官方 BLoC Part-Part Of 模式:每个 _bloc.dart 文件都必须通过 part 指令引入对应的 _event.dart 和 _state.dart 文件。每个事件/状态文件都必须包含指向对应 BLoC 文件的 part of 指令,以确保它们处于同一库作用域并共享私有成员。
    // auth_bloc.dart
    part 'auth_event.dart';
    part 'auth_state.dart';
    
    class AuthBloc extends Bloc<AuthEvent, AuthState> { ... }
    
    // auth_event.dart
    part of 'auth_bloc.dart';
    
    // auth_state.dart
    part of 'auth_bloc.dart';
    
  • 强制目录结构:每组 BLoC 功能都必须位于 bloc/ 文件夹下独立的子目录中。严格禁止使用扁平的 bloc/ 目录。
    presentation/bloc/
    └── <bloc_name>/
        ├── <bloc_name>_bloc.dart
        ├── <bloc_name>_event.dart
        └── <bloc_name>_state.dart
    
  • 加载状态要求:异步操作前必须始终发出 Loading,随后发出 Success 或 Error。绝不能跳过加载状态。
  • 并发处理:对于需要防抖(搜索)或节流(按钮)的事件,使用 transformers(例如 restartable()、droppable())。
  • UI 不含逻辑:Widget 不得包含业务逻辑、编排逻辑,也不得直接调用外部服务。它们只能分发事件,并根据 BLoC 状态构建 UI。

BLoC Widget 用法

  • 使用 BlocBuilder 根据状态局部重建 UI
  • 使用 BlocListener 处理副作用(导航、snackbar、对话框)
  • 需要同时重建 UI 和处理副作用时,使用 BlocConsumer
  • 使用 context.read<Bloc>().add(Event()) 分发事件
  • 使用 context.watch<Bloc>().state 实现响应式重建(仅限 build() 内)

工作流:实现状态管理

添加或更新 BLoC 时,请遵循以下顺序执行工作流。复制此清单以跟踪进度。

任务进度
  • 步骤 1:定义事件和状态。 确保它们使用 Equatable 并设置正确的 props,或使用 freezed。
  • 步骤 2:实现异步操作。 确认所有异步操作都遵循 Loading → Success/Error 模式。
  • 步骤 3:重构 UI。 确保 UI Widget 中不包含编排逻辑或业务逻辑;它们只能分发事件。
  • 步骤 4:验证数据源。 确保所有 SDK/API 调用都只存在于 DataSources 中。
  • 步骤 5:检查设计令牌。 确保没有使用硬编码的颜色、间距或字体排版。
  • 步骤 6:格式化代码。 确保代码已使用 dart format 格式化。

依赖注入

  • 使用 injectable 进行依赖注入和服务定位
  • 标准化注入:
    • 屏幕专用 BLoC 使用 @injectable,确保每次访问屏幕时都会创建新实例。
    • 全局或共享 BLoC(例如 AuthBloc、ThemeBloc、SettingsBloc、PasswordBloc)使用 @lazySingleton。
  • 按功能合理组织 BLoC,并确保严格分离关注点

导航与路由

  • 动态路由:严格禁止在 GoRouter 配置中硬编码路由字符串。请使用 AppRoutes 中的静态常量。
  • 集中管理 BLoC:当多个屏幕或同一功能分支需要共享 BLoC 时,必须通过 app_router.dart 中的 ShellRoute 或 BlocProvider 注入。
  • 禁止本地 Provider:如果某个功能集需要使用 BLoC,请避免在单个屏幕的 build() 方法中使用 BlocProvider。
  • 路由参数使用基本类型:严格禁止将复杂对象(BLoC、ChangeNotifiers、Entity 实例)作为路由参数传递。只传递基本类型的 ID/Key,并在目标屏幕中通过 Repository 或 BLoC 注入获取数据。

评论

支持 Markdown