Loading...
Loading...
Compare original and translation side by side
pubspec.yamlanalysis_options.yamlprint()dart:developerlog().g.dart.freezed.dart.gr.dart.gitignorepubspec.yamlanalysis_options.yamlprint()dart:developerlog().g.dart.freezed.dart.gr.dart.gitignoredynamicstrict-castsstrict-inferencestrict-raw-types!if (value case var v?)this.fieldcatch (e)onErrorErrorasyncasyncawaitlatelateStringBuffer+constconstFutureawaitunawaited()varfinalfinalconstpackage:ListMapif-caseis(String, int)print()dart:developerlog()print()dynamicstrict-castsstrict-inferencestrict-raw-types!if (value case var v?)this.fieldcatch (e)onErrorasyncawaitlateStringBuffer+constawaitunawaited()finalconstpackage:ListMapif-caseis(String, int)dart:developerlog()print()build()_build*()build()_build*()constconstconst []const {}constconstconstconst []const {}constValueKeyGlobalKeyUniqueKeybuild()ObjectKeyValueKeyGlobalKeybuild()UniqueKeyObjectKeyTheme.of(context).colorSchemeColors.redTheme.of(context).textThemeTextStyleTheme.of(context).colorSchemeColors.redTheme.of(context).textThemeTextStylebuild()Future.then()asyncbuild().listen()build()setState()build()build()Future.then()build().listen()setState()ref.watchref.watchcopyWith()==hashCodeEquatablefreezedListMapcopyWith()==hashCodeEquatablefreezedListMap@action.value.obsReactionDisposer@action.value.obsReactionDisposerAsyncValueisLoadingisErrorhasData// BAD — boolean flag soup allows impossible states
class UserState {
bool isLoading = false;
bool hasError = false; // isLoading && hasError is representable!
User? user;
}
// GOOD (immutable approach) — sealed types make impossible states unrepresentable
sealed class UserState {}
class UserInitial extends UserState {}
class UserLoading extends UserState {}
class UserLoaded extends UserState {
final User user;
const UserLoaded(this.user);
}
class UserError extends UserState {
final String message;
const UserError(this.message);
}
// GOOD (reactive approach) — observable enum + data, mutations via reactivity API
// enum UserStatus { initial, loading, loaded, error }
// Use your solution's observable/signal to wrap status and data separatelyAsyncValueisLoadingisErrorhasData// 不良示例——布尔标志会导致不可能的状态组合
class UserState {
bool isLoading = false;
bool hasError = false; // 可能出现isLoading && hasError的矛盾状态!
User? user;
}
// 良好示例(不可变方式)——密封类型避免不可能的状态组合
sealed class UserState {}
class UserInitial extends UserState {}
class UserLoading extends UserState {}
class UserLoaded extends UserState {
final User user;
const UserLoaded(this.user);
}
class UserError extends UserState {
final String message;
const UserError(this.message);
}
// 良好示例(响应式方式)——可观察枚举+数据,通过响应式API修改状态
// enum UserStatus { initial, loading, loaded, error }
// 使用对应方案的可观察对象/signal分别包装状态和数据constconst.listen()dispose()close().listen()mountedsetStateBuildContextawaitcontext.mountedBuildContext.listen()dispose()close().listen()setStatemountedawaitBuildContextcontext.mountedBuildContextsetStateValueNotifiersetStateValueNotifiersetState()constRepaintBoundaryAnimatedBuildersetState()constRepaintBoundaryAnimatedBuilderbuild()build()MediaQuery.of(context)MediaQuery.sizeOf(context)build()build()MediaQuery.of(context)MediaQuery.sizeOf(context)Image.assetcacheWidthcacheHeightImage.assetcacheWidthcacheHeightListView.builderGridView.builderListView(children: [...])deferred asListView.builderGridView.builderListView(children: [...])deferred asOpacityAnimatedOpacityFadeTransitionoperator ==constIntrinsicHeightIntrinsicWidthOpacityAnimatedOpacityFadeTransitionoperator ==constIntrinsicHeightIntrinsicWidthpumpWidgetpumpfind.byTypefind.textfind.byKeypumpAndSettlepump(Duration)pumpWidgetpumpfind.byTypefind.textfind.byKeypumpAndSettlepump(Duration)SemanticsExcludeSemanticsMergeSemanticssemanticLabelSemanticsExcludeSemanticsMergeSemanticssemanticLabelonPressedonPressedSafeAreaAndroidManifest.xmlInfo.plistSafeAreaAndroidManifest.xmlInfo.plistLayoutBuilderMediaQueryFlexibleExpandedFittedBoxLayoutBuilderMediaQueryFlexibleExpandedFittedBox--dart-define.env.gitignore--dart-define.env.gitignore^1.2.3flutter pub outdatedpubspec.yaml^1.2.3flutter pub outdatedpubspec.yamlpackage:other/src/internal.dartpath: ../../analysis_options.yamlpackage:other/src/internal.dartpath: ../../analysis_options.yamlNavigator.pushMap<String, dynamic>Object?Navigator.pushMap<String, dynamic>Object?FlutterError.onErrorPlatformDispatcher.instance.onErrorErrorWidget.builderrunApprunZonedGuardedFlutterError.onErrorPlatformDispatcher.instance.onErrorErrorWidget.builderrunApprunZonedGuardedififanalysis_options.yamlstrict-casts: truestrict-inference: truestrict-raw-types: trueanalysis_options.yamlstrict-casts: truestrict-inference: truestrict-raw-types: true// ignore:flutter analyze// ignore:flutter analyzeprefer_const_constructorsavoid_printunawaited_futuresprefer_final_localsalways_declare_return_typesavoid_catches_without_on_clausesalways_use_package_importsprefer_const_constructorsavoid_printunawaited_futuresprefer_final_localsalways_declare_return_typesavoid_catches_without_on_clausesalways_use_package_imports| Principle | BLoC/Cubit | Riverpod | Provider | GetX | MobX | Signals | Built-in |
|---|---|---|---|---|---|---|---|
| State container | | | | | | | |
| UI consumer | | | | | | | |
| Selector | | | | N/A | computed | | N/A |
| Side effects | | | | | | | callbacks |
| Disposal | auto via | | auto via | | | manual | |
| Testing | | | | | store directly | signal directly | widget test |
| 原则 | BLoC/Cubit | Riverpod | Provider | GetX | MobX | Signals | 内置方案 |
|---|---|---|---|---|---|---|---|
| 状态容器 | | | | | | | |
| UI消费者 | | | | | | | |
| 选择器 | | | | 无 | computed | | 无 |
| 副作用 | | | | | | | 回调 |
| 资源释放 | 由 | | 由 | | | 手动处理 | |
| 测试 | | | 直接测试 | 测试中使用 | 直接测试store | 直接测试signal | Widget测试 |