flutter-bloc
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBLoC Pattern
BLoC模式
- Sealed States & Events: Always use for both States and Events to ensure exhaustive UI handling and compile-time safety.
sealed class - Immutability: All States, Events, and Domain Entities MUST be immutable (using and
finalorEquatable).freezed - Official BLoC Part-Part Of Pattern: Every file MUST include its corresponding
_bloc.dartand_event.dartfiles using_state.dartdirectives. Each event/state file MUST have apartdirective pointing back to the bloc file. This ensures a single library scope and shared private members.part ofdart// 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'; - Mandatory Directory Structure: Every BLoC feature set MUST reside in its own sub-directory within the folder. Flat
bloc/directories are STRICTLY prohibited.bloc/textpresentation/bloc/ └── <bloc_name>/ ├── <bloc_name>_bloc.dart ├── <bloc_name>_event.dart └── <bloc_name>_state.dart - Loading State Mandate: ALWAYS emit before async work, then
LoadingorSuccess. Never skip the loading state.Error - Concurrency: Use (e.g.,
transformers,restartable()) for events requiring debouncing (search) or throttling (buttons).droppable() - Zero-Logic UI: Widgets MUST NOT contain business logic, orchestration logic, or direct calls to external services. They should ONLY dispatch events and build UI based on BLoC states.
- 密封状态与事件:始终对状态和事件使用,以确保全面的UI处理和编译时安全。
sealed class - 不可变性:所有状态、事件和领域实体必须是不可变的(使用以及
final或Equatable实现)。freezed - 官方BLoC Part-Part Of 模式:每个文件必须使用
_bloc.dart指令引入对应的part和_event.dart文件。每个事件/状态文件必须包含指向对应bloc文件的_state.dart指令。这可以确保单一库作用域和私有成员共享。part ofdart// 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/textpresentation/bloc/ └── <bloc_name>/ ├── <bloc_name>_bloc.dart ├── <bloc_name>_event.dart └── <bloc_name>_state.dart - 加载状态强制要求:在执行异步操作前必须先抛出状态,之后再返回
Loading或Success状态。绝对不能省略加载状态。Error - 并发处理:对于需要防抖(搜索功能)或节流(按钮点击)的事件,使用(例如
transformers、restartable())。droppable() - 零逻辑UI:Widgets中不能包含业务逻辑、编排逻辑,也不能直接调用外部服务。它们只应该派发事件,并基于BLoC状态构建UI。
BLoC Widget Usage
BLoC Widget使用规范
- for local UI rebuilds based on state
BlocBuilder - for side effects (navigation, snackbars, dialogs)
BlocListener - when both rebuild and side effects are needed
BlocConsumer - for dispatching events
context.read<Bloc>().add(Event()) - for reactive rebuilds (inside
context.watch<Bloc>().stateonly)build()
- 使用基于状态实现局部UI重绘
BlocBuilder - 使用处理副作用(导航、snackbars、弹窗)
BlocListener - 同时需要重绘和副作用时使用
BlocConsumer - 使用派发事件
context.read<Bloc>().add(Event()) - 仅在方法内部使用
build()实现响应式重绘context.watch<Bloc>().state
BLoC Submission Checklist
BLoC提交检查清单
- Events and States use with correct
Equatableprops - All async operations follow pattern
Loading → Success/Error - No business logic in UI widgets
- No SDK/API calls outside DataSources
- Zero hardcoded colors, spacing, or typography \u2014 use design tokens (,
AppColors)AppSpacing - Code formatted with
dart format
- 事件和状态使用并配置正确的
Equatableprops - 所有异步操作遵循模式
Loading → Success/Error - UI Widget中无业务逻辑
- 无在DataSource之外调用SDK/API的情况
- 无硬编码的颜色、间距或字体样式——使用设计令牌(、
AppColors)AppSpacing - 代码已使用格式化
dart format
Dependency Injection
依赖注入
- Use for dependency injection and service location
injectable - Standardized Injection:
- Use for screen-specific BLoCs to ensure a fresh instance per screen access.
@injectable - Use for global or shared BLoCs (e.g.,
@lazySingleton,AuthBloc,ThemeBloc,SettingsBloc).PasswordBloc
- Use
- Organize blocs logically by feature and ensure strict separation of concerns
- 使用实现依赖注入和服务定位
injectable - 标准化注入规则:
- 页面专属的BLoC使用注解,确保每次访问页面都生成新的实例。
@injectable - 全局或共享的BLoC使用注解(例如
@lazySingleton、AuthBloc、ThemeBloc、SettingsBloc)。PasswordBloc
- 页面专属的BLoC使用
- 按照功能逻辑组织bloc,确保严格的关注点分离
Navigation & Routing
导航与路由
- Dynamic Routes: STRICTLY prohibit hardcoded route strings in configuration. Use static constants in
GoRouter.AppRoutes - Centralized BLoCs: BLoC providers MUST be injected via or
ShellRouteinBlocProviderwhen shared across multiple screens or within a feature branch.app_router.dart - No Local Providers: Avoid in individual screen
BlocProvidermethods if the BLoC is needed by a feature set.build() - Primitive Route Arguments: STRICTLY prohibit passing complex objects (BLoCs, ChangeNotifiers, Entity instances) as route arguments. Pass only primitive IDs/Keys and fetch data in the destination screen using or
Repositoryinjection.Bloc
- 动态路由:严格禁止在配置中使用硬编码的路由字符串。请使用
GoRouter中定义的静态常量。AppRoutes - 集中式BLoC:当BLoC需要在多个页面共享或属于某个功能分支时,必须通过中的
app_router.dart或ShellRoute注入。BlocProvider - 避免本地提供器:如果BLoC是某个功能集所需,不要在单独页面的方法中使用
build()注入。BlocProvider - 基础类型路由参数:严格禁止传递复杂对象(BLoCs、ChangeNotifiers、实体实例)作为路由参数。仅传递基础类型的ID/键,在目标页面通过或
Repository注入获取数据。Bloc