簡體   English   中英

首先:將 object 轉換為可編碼的 object 失敗 - 然后:HydratedCubit 未水合

[英]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 datalists的用例。 只有在data simple的情況下才可以使用。

上述陳述的證明:

  1. 我們如何在 hydrated bloc #2324 中保留列表 - 未決問題
  2. 問題 [hydrated_bloc] 復雜的例子 #2392

解決方案

對於此類要求,我建議您使用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 都需要有toJsonfromJson方法。 因此,使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM