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

Flutter Hydrated Cubit状态无法持久化:初始状态覆盖已加载状态

问题解决:Hydrated Cubit状态被初始状态覆盖的修复方案

核心问题分析

你的日志显示fromJson已成功加载持久化状态,但随后被初始状态覆盖,根源在于以下几点:

  1. 状态类未正确实现序列化/反序列化方法,且未重写Equatable的props属性
  2. 可能存在Cubit重复实例化或手动触发初始状态的操作
  3. 未确保HydratedStorage的正确初始化

具体修复步骤

1. 补全状态类的序列化逻辑

你的DefectSectionsState、DefectSection、DefectItem类需要实现fromMap和toMap方法,同时重写Equatable的props以保证状态对比正确性:

class DefectSectionsState extends Equatable {
  final List<DefectSection> defectSections;
  const DefectSectionsState({
    required this.defectSections,
  });

  factory DefectSectionsState.initial() => const DefectSectionsState(
        defectSections: [
          DefectSection(
            sectionName: 'FABRIC',
            defectItems: [DefectItem(name: 'Cotton')],
          ),
          DefectSection(
            sectionName: 'COLOR',
            defectItems: [DefectItem(name: 'Crimson')],
          ),
          DefectSection(
            sectionName: 'SEWING',
            defectItems: [DefectItem(name: 'Lockstitch')],
          ),
        ],
      );

  // 反序列化方法
  factory DefectSectionsState.fromMap(Map<String, dynamic> map) {
    return DefectSectionsState(
      defectSections: List<DefectSection>.from(
        map['defectSections'].map((x) => DefectSection.fromMap(x)),
      ),
    );
  }

  // 序列化方法
  Map<String, dynamic> toMap() {
    return {
      'defectSections': defectSections.map((x) => x.toMap()).toList(),
    };
  }

  @override
  List<Object> get props => [defectSections];
}

class DefectSection extends Equatable {
  final String sectionName;
  final List<DefectItem> defectItems;
  const DefectSection({
    required this.sectionName,
    required this.defectItems,
  });

  factory DefectSection.fromMap(Map<String, dynamic> map) {
    return DefectSection(
      sectionName: map['sectionName'],
      defectItems: List<DefectItem>.from(
        map['defectItems'].map((x) => DefectItem.fromMap(x)),
      ),
    );
  }

  Map<String, dynamic> toMap() {
    return {
      'sectionName': sectionName,
      'defectItems': defectItems.map((x) => x.toMap()).toList(),
    };
  }

  @override
  List<Object> get props => [sectionName, defectItems];
}

class DefectItem extends Equatable {
  final String name;
  const DefectItem({required this.name});

  factory DefectItem.fromMap(Map<String, dynamic> map) {
    return DefectItem(name: map['name']);
  }

  Map<String, dynamic> toMap() {
    return {'name': name};
  }

  @override
  List<Object> get props => [name];
}

2. 正确初始化HydratedStorage

在main函数中必须先初始化存储,否则持久化逻辑无法正常工作:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // 初始化Hydrated存储目录
  HydratedBloc.storage = await HydratedStorage.build(
    storageDirectory: await getApplicationDocumentsDirectory(),
  );
  runApp(const YourApp());
}

3. 避免Cubit重复实例化或手动覆盖状态

  • 确保在Widget树中仅创建一次Cubit实例,比如使用BlocProvider的懒加载模式:
    BlocProvider(
      create: (context) => DefectSectionsCubit(),
      lazy: true, // 默认开启,仅在需要时创建实例
      child: YourPage(),
    )
    
  • 检查代码中是否存在手动调用emit(DefectSectionsState.initial())的逻辑,这类操作会直接覆盖已加载的持久化状态。

4. 保持Cubit代码简洁

你的Cubit代码无需修改构造函数,保持原有结构即可:

class DefectSectionsCubit extends HydratedCubit<DefectSectionsState> {
  DefectSectionsCubit() : super(DefectSectionsState.initial()) {
    print("Cubit initialized");
  }

  @override
  DefectSectionsState? fromJson(Map<String, dynamic> json) {
    print("Loaded state from storage");
    return DefectSectionsState.fromMap(json);
  }

  @override
  Map<String, dynamic>? toJson(DefectSectionsState state) {
    print("Saved state to storage");
    return state.toMap();
  }

  // 自定义状态更新方法示例
  void updateSections(List<DefectSection> newSections) {
    emit(DefectSectionsState(defectSections: newSections));
  }
}

内容的提问来源于stack exchange,提问作者kk-at-cbx

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 17:40:39