使用HydratedCubit实现Todo列表持久化失败问题求助
问题原因及解决方案
核心问题
HydratedCubit无法保存列表的根本原因是Todo模型未实现序列化/反序列化逻辑,且你的TodoListState代码存在拼写错误与逻辑混乱,导致JSON转换链断裂。
具体问题点
- Todo模型缺失序列化能力:JSON无法直接识别自定义
Todo对象,必须为其添加json_serializable支持,否则即使给State加注解,列表里的Todo依然无法被转成可存储的JSON格式。 - TodoListState代码错误:你写的
FoodListState是拼写错误(应为TodoListState),生成的.g.dart文件里误用了TodoModel而非Todo,导致序列化逻辑完全失效。 - 序列化链不完整:State的序列化依赖内部所有自定义对象的序列化能力,必须同时处理
Todo和TodoListState的JSON转换。
分步修复方案
1. 为Todo模型添加序列化支持
修改todo.dart,添加json_serializable注解及对应的转换方法:
import 'package:equatable/equatable.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:uuid/uuid.dart'; part 'todo.g.dart'; Uuid uuid = const Uuid(); @JsonSerializable() class Todo extends Equatable { final String id; final String desc; final double menge; Todo({ String? id, required this.desc, required this.menge, }) : id = id ?? uuid.v4(); // 从JSON转Todo对象 factory Todo.fromJson(Map<String, dynamic> json) => _$TodoFromJson(json); // 从Todo对象转JSON Map<String, dynamic> toJson() => _$TodoToJson(this); @override List<Object?> get props => [id, desc, menge]; }
2. 修复TodoListState的代码错误
修改todo_list_state.dart,修正拼写错误并关联正确的序列化逻辑:
part of 'todo_list_cubit.dart'; import 'package:equatable/equatable.dart'; import 'package:json_annotation/json_annotation.dart'; import '../models/todo.dart'; part 'todo_list_state.g.dart'; @JsonSerializable() class TodoListState extends Equatable { final List<Todo> todos; const TodoListState({required this.todos}); factory TodoListState.initial() { return const TodoListState(todos: []); } // 从JSON转State factory TodoListState.fromJson(Map<String, dynamic> json) => _$TodoListStateFromJson(json); // 从State转JSON Map<String, dynamic> toJson() => _$TodoListStateToJson(this); @override List<Object?> get props => [todos]; }
3. 修正HydratedCubit的序列化方法
修改todo_list_cubit.dart,直接使用State的fromJson/toJson方法:
import 'package:hydrated_bloc/hydrated_bloc.dart'; import '../models/todo.dart'; part 'todo_list_state.dart'; part 'todo_list_cubit.g.dart'; class TodoListCubit extends HydratedCubit<TodoListState> { TodoListCubit() : super(TodoListState.initial()); // 示例:添加Todo的方法 void addTodo({required String desc, required double menge}) { final newTodo = Todo(desc: desc, menge: menge); emit(TodoListState(todos: [...state.todos, newTodo])); } @override TodoListState? fromJson(Map<String, dynamic> json) { return TodoListState.fromJson(json); } @override Map<String, dynamic>? toJson(TodoListState state) { return state.toJson(); } }
4. 生成序列化代码并初始化存储
- 运行命令生成
.g.dart文件:flutter pub run build_runner build - 在
main.dart中初始化HydratedStorage(必须确保在runApp之前执行):import 'package:flutter/material.dart'; import 'package:hydrated_bloc/hydrated_bloc.dart'; import 'package:path_provider/path_provider.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); // 初始化本地存储目录 HydratedBloc.storage = await HydratedStorage.build( storageDirectory: await getApplicationDocumentsDirectory(), ); runApp(const MyApp()); }
验证逻辑
完成上述修改后,添加Todo后退出应用,重新启动时列表会自动恢复,因为:
- 每个
Todo能转成JSON对象 TodoListState能将List<Todo>转成JSON数组- HydratedCubit会自动将State的JSON数据存储到本地,并在启动时读取恢复
内容的提问来源于stack exchange,提问作者Fabian M
相关产品推荐
相关产品推荐

