[英]First: Converting object to an encodable object failed - then: HydratedCubit isn't hydrated
以下情況:我想用 Cubit 做一個 ToDo 列表。 離開應用程序后待辦事項列表不會消失,我找到了 package hydrated Bloc。 當我使用 FromJson 和 ToJson 的 2 個覆蓋方法創建 HydratedCubit,在 ToDoState 內部創建它們並執行它時,我得到一個異常,“將 object 轉換為可編碼的 object 失敗:'Todo' 的實例”。 經過研究,我發現 JSON 無法轉換這樣的 model,您必須先使用有效的 From 和 To 函數覆蓋這些模型。 我用 package “json 可序列化”試過這個。 在這里我不得不問自己在哪個class我必須在Todo model或todo state中添加“@JsonSerializable()”,其中出現錯誤? 我決定為我的 todostate 添加 @,因為將它添加到 Todo model 並沒有改變任何東西。 在這個 package 為我創建了“todo_list_state.g.dart”之后,我不再收到錯誤,但是:它也沒有保存列表,看起來 HydratedCubit 被“忽略”了。 這里有一些代碼片段:
首先,我向您展示 Todo Model:
Uuid uuid = const Uuid();
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();
}
我遺漏了 to string 和 props...正如我之前提到的,我試圖在這個 class 中添加 JsonSerializableGenerator,但這並沒有改變什么。 這是我的 TodoListState:
part of 'todo_list_cubit.dart';
@JsonSerializable()
class TodoListState extends Equatable {
final List<Todo> todos;
factory TodoListState.initial() {
return TodoListState(todos: []);
}
Map<String, dynamic>toMap() => _$FoodListStateToMap(this, food);
factory FoodListState.fromMap(Map<String, dynamic> map) => _$FoodListStateFromMap(map);
}
以下是“todo_list_state.g.dart”中生成的函數:
TodoListState _$TodoListStateFromMap(Map<String, dynamic> map) {
return TodoListState (
todo: map['todo'] as List<TodoModel>,
);
}
Map<String, dynamic> _$TodoListStateToMap(TodoListState instance, List<TodoModel> todo) {
return {
'todo': todo,
};
}
最后,在這里我的 Cubit 函數覆蓋了 From 和 To:
@override
TodoListState? fromJson(Map<String, dynamic> json) {
return TodoListState.fromMap(json);
}
@override
Map<String, dynamic>? toJson(TodoListStatestate) {
return state.toMap();
}
那么有人知道為什么我的 Hydrated Cubit 沒有保存我的列表嗎? 還是我必須轉換 Model 但不知道如何轉換?...感謝您的幫助。 謝謝
hydrated_bloc
保留列表直到日期請務必注意,
Hydrated_bloc
不適用於涉及存儲complex data
和lists
的用例。 只有在data
simple
的情況下才可以使用。
上述陳述的證明:
對於此類要求,我建議您使用shared_preferences 。
TodoCubit.dart
class TodoCubit extends HydratedBloc<TodoCubit, TodoState> {
TodoCubit() : super(ToDoInitial());
@override
TodoState? fromJson(Map<String, dynamic> json) {
return TodoState.fromJson(json);
}
@override
Map<String, dynamic>? toJson(TodoState state) {
return state.toJson();
}
saveTodo(String todo, String date) {
emit(TodoState(presentTodo: Todo(todo: todo, day: date)));
}
}
ToDoState.dart
class TodoState extends Equatable {
final Todo presentTodo;
const TodoState({required this.presentTodo});
factory TodoState.fromJson(Map<String, dynamic> json) {
return TodoState(presentTodo: Todo(todo: json['todo'], day: json['day']));
}
Map<String, dynamic> toJson() =>
{'todo': presentTodo.todo, 'day': presentTodo.day};
@override
List<Object?> get props => [presentTodo];
}
class Todo {
String todo;
String day;
Todo({required this.todo, required this.day});
@override
String toString() {
return "todo: " + todo + " day: " + day;
}
}
class ToDoInitial extends TodoState {
ToDoInitial() : super(presentTodo: Todo(todo: '', day: ''));
}
家.dart
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(height: 10),
Text(state.presentTodo.toString()),
ElevatedButton(
style: Constants.kElevatedButtonStyle,
onPressed: () {
context
.read<TodoCubit>()
.saveTodo('Drink Water ', 'Tuesday');
},
child: const Text(
'Add Dummy Todo',
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.bold),
),
),
],
),
);
主要.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
HydratedBloc.storage = await HydratedStorage.build(
storageDirectory: await getTemporaryDirectory(),
);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => TodoCubit(),
child: MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
appBarTheme: const AppBarTheme()
.copyWith(backgroundColor: const Color.fromRGBO(18, 26, 28, 1)),
primarySwatch: Colors.blue,
),
home: const Home(),
),
);
}
}
Output:
model 和 states 都需要有toJson
和fromJson
方法。 因此,使用JsonSerializable
的方法是正確的。 但是,將對象與 json 相互轉換是了解如何在沒有代碼生成工具的情況下如何做的一件非常重要的事情。 這些可能是樣板文件,並不總是能正確轉換復雜的對象。 手動執行時,調試也更容易。 因此,在您的情況下,對 model 的添加將是:
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();
factory Todo.fromJson(Map<String, dynamic> json){
return Todo(id: json['id'],
desc: json['desc'],
menge: json['menge'],);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'desc': desc,
'menge': menge,
};
}
}
然后,在您的狀態下(同樣,我不會使用JsonSerializable
):
class TodoListState extends Equatable {
final List<Todo> todos;
TodoListState({this.todos = const <Todo>[]});
factory TodoListState.fromJson(Map<String, dynamic> json) {
var todos = <Todo>[];
for (var item in json['todos']) {
todos.add(Todo.fromJson(item));
}
return TodoListState(todos: todos);
}
Map<String, dynamic> toJson() {
var jsonTodoList = <Map<String, dynamic>>[];
for (var item in todos) {
jsonTodoList.add(item.toJson());
}
return {
'todos': jsonTodoList,
};
}
}
然后在你的手肘中沒有任何變化
@override
TodoListState? fromJson(Map<String, dynamic> json) {
return TodoListState.fromJson(json);
}
@override
Map<String, dynamic>? toJson(TodoListState state) {
return state.toJson();
}
除了你可能想在轉換周圍添加各種 null 安全檢查,因為我省略了與問題主題無關的所有方面。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.