You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Hydrated Bloc v5及以上版本状态持久化与多数据读取实现问题

新版本Hydrated Bloc(bloc v5+)持久化实现方案

初始化配置

bloc v5及以上版本已经移除了BlocSupervisor组件,hydrated_bloc也已经完成适配,不需要自行实现BlocObserver来完成持久化逻辑,所有持久化能力已经内置封装,仅需要在应用启动前完成存储初始化即可:

import 'package:flutter/material.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:path_provider/path_provider.dart';

void main() async {
  // 确保Flutter引擎初始化完成
  WidgetsFlutterBinding.ensureInitialized();
  // 构建Hydrated存储实例,可选择存储目录
  final storage = await HydratedStorage.build(
    // 临时目录:应用卸载时会清除
    storageDirectory: await getTemporaryDirectory(),
    // 永久目录可替换为:await getApplicationDocumentsDirectory()
  );
  // 全局赋值存储实例,所有HydratedBloc共用
  HydratedBloc.storage = storage;
  runApp(const MyApp());
}
现有代码的问题修正

你当前的实现存在冗余逻辑和错误,按照以下规则修改即可实现多字段复杂状态的自动持久化:

  1. 无需手动调用fromJson、toJson方法,也不需要手动读写HydratedBloc.storage。HydratedBloc会自动在Bloc实例初始化时调用fromJson恢复存储的状态,在状态变更时自动调用toJson序列化存储新状态,所有逻辑都是自动触发的。
  2. 无需单独编写初始化事件读取存储内容,Bloc初始化时如果存在已存储的状态,会自动覆盖你传入构造函数的默认状态,无需手动处理。
  3. toJson方法的参数类型需要和你的Bloc状态类型(ClassAState)一致,否则框架无法正常调用。
  4. 注意toJson返回的Map的key拼写要和fromJson读取的key完全一致,你现有代码中rehicleRevsPerDist拼写错误(多了一个h),会导致该字段读取失败。
多字段复杂状态持久化实现示例

你不需要手动拼接JSON字符串,只要在toJson中返回包含所有需要持久化字段的Map,在fromJson中从传入的Map读取字段构建状态对象即可,框架会自动完成序列化/反序列化操作。
修正后的完整Bloc代码如下:

class ClassABLoC extends HydratedBloc<ClassAEvent, ClassAState> {
  // 传入默认状态,有存储数据时会自动覆盖
  ClassABLoC() : super(ClassAState.dataNotReceived());

  @override
  Stream<ClassAState> mapEventToState(ClassAEvent event) async* {
    if (event is ClassAValidate) {
      yield ClassAState.validated(
        theEvent: event,
        numberValidated: validateTheInput(event.numberVal, event.vehicleNumber),
        distanceValidated: validateTheInput(event.distanceVal, event.vehicleDistanceTraveled),
        yearValidated: validateTheInput(event.yearVal, event.vehicleYear),
        vinValidated: validateTheInput(event.vinVal, event.vin),
        licensePlateValidated: validateTheInput(event.licensePlateVal, event.vehicleLicensePlate),
        revsPerDistValidated: validateTheInput(event.revsPerDistVal, event.vehicleRevsPerDist),
        fuelTypeValidated: validateTheInput(event.fuelTypeVal, event.fuelType),
        fuelCapacityValidated: validateTheInput(event.fuelCapacityVal, event.fuelCapacity),
        siteValidated: validateTheInput(event.siteVal, event.vehicleSite),
        numberError: event.numberVal?.validationFailedMsg,
        distanceError: event.distanceVal?.validationFailedMsg,
        yearError: event.yearVal?.validationFailedMsg,
        vinError: event.vinVal?.validationFailedMsg,
        licensePlateError: event.licensePlateVal?.validationFailedMsg,
        revsPerDistError: event.revsPerDistVal?.validationFailedMsg,
        fuelTypeError: event.fuelTypeVal?.validationFailedMsg,
        fuelCapacityError: event.fuelCapacityVal?.validationFailedMsg,
        siteError: event.siteVal?.validationFailedMsg,
      );
    } else if (event is StoreDataEvent) {
      // 直接yield要存储的状态即可,框架自动触发持久化
      yield StoreDataState(
        vehicleNumber: event.vehicleNumber,
        vehicleYear: event.vehicleYear,
        vehicleRevsPerDist: event.vehicleRevsPerDist,
        vehicleDistanceTraveled: event.vehicleDistanceTraveled,
        vin: event.vin,
        vehicleLicensePlate: event.vehicleLicensePlate,
        fuelCapacity: event.fuelCapacity,
        fuelType: event.fuelType,
        vehicleSite: event.vehicleSite,
      );
    }
  }

  // 序列化状态到Map,框架自动转JSON存储
  @override
  Map<String, dynamic>? toJson(ClassAState state) {
    if (state is StoreDataState) {
      return {
        'vehicleNumber': state.vehicleNumber,
        'vehicleDistanceTraveled': state.vehicleDistanceTraveled,
        'vehicleLicensePlate': state.vehicleLicensePlate,
        'vin': state.vin,
        'vehicleRevsPerDist': state.vehicleRevsPerDist, // 修正拼写错误
        'vehicleSite': state.vehicleSite,
        'vehicleYear': state.vehicleYear,
        'fuelCapacity': state.fuelCapacity,
        'fuelType': state.fuelType,
        'distUnit': state.distUnits,
      };
    }
    // 其他类型的状态如果不需要持久化,返回null即可
    return null;
  }

  // 反序列化存储的Map为状态对象,框架初始化时自动调用
  @override
  ClassAState fromJson(Map<String, dynamic> json) {
    return ProgramDataTracSVTState(
      vehicleNumber: (json['vehicleNumber'] as String?)?.isEmpty ?? true
          ? "HARDCODED"
          : json['vehicleNumber'] as String,
      vehicleDistanceTraveled: (json['vehicleDistanceTraveled'] as String?)?.isEmpty ?? true
          ? "HARDCODED VALUE"
          : json['vehicleDistanceTraveled'] as String,
      vehicleLicensePlate: (json['vehicleLicensePlate'] as String?) ?? "",
      vin: (json['vin'] as String?)?.isEmpty ?? true
          ? "HARDCODED VALUE"
          : json['vin'] as String,
      vehicleRevsPerDist: (json['vehicleRevsPerDist'] as String?)?.isEmpty ?? true
          ? "500"
          : json['vehicleRevsPerDist'] as String,
      vehicleSite: (json['vehicleSite'] as String?)?.isEmpty ?? true
          ? "Home Base Site"
          : json['vehicleSite'] as String,
      vehicleYear: (json['vehicleYear'] as String?)?.isEmpty ?? true
          ? "2018"
          : json['vehicleYear'] as String,
      fuelCapacity: (json['fuelCapacity'] as String?) ?? "",
      fuelType: (json['fuelType'] as String?)?.isEmpty ?? true
          ? "Diesel"
          : json['fuelType'] as String,
      distUnits: (json['distUnit'] as String?)?.isEmpty ?? true
          ? "None"
          : json['distUnit'] as String,
    );
  }
}

内容的提问来源于stack exchange,提问作者TarHalda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 20:54:05