Обновление базы данных Hive в приложении Flutter с помощью нового поляAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Обновление базы данных Hive в приложении Flutter с помощью нового поля

Сообщение Anonymous »

TL;DR. Я хочу поддержать обновление моего приложения до новой версии базы данных с новым полем. Я чувствую, что перепробовал все и не могу найти решение, в котором оно корректно обрабатывало бы чтение старых полей, а также чтение новых полей.
У меня есть приложение andorid flutter, которое хранит рецепты (в коробка-улей), в рецептах у меня есть ингредиенты, это список актеров, который имеет свою собственную модель и адаптер - видимого поля нет, я думаю, оно должно существовать в поле рецепта (при просмотре через Chrome).
Я пытаюсь добавить новое поле и поддержать обновление старой модели Hive, но постоянно сталкиваюсь с ошибками.
В исходной версии моего app у меня был следующий код для модели и адаптера для ингредиентов, поля подготовки не было:

Код: Выделить всё

import 'package:hive/hive.dart';

class Ingredient {
final String name;
final String quantity;
final String unit;

Ingredient({
required this.name,
required this.quantity,
required this.unit,
});
}

class IngredientAdapter extends TypeAdapter {
@override
final int typeId = 1; // Unique identifier for the adapter

@override
Ingredient read(BinaryReader reader) {
return Ingredient(
name: reader.readString(),
quantity: reader.readString(),
unit: reader.readString(),
);
}

@override
void write(BinaryWriter writer, Ingredient obj) {
writer.writeString(obj.name);
writer.writeString(obj.quantity);
writer.writeString(obj.unit);
}
}
Однако, когда я реализовал новое поле для ингредиентов, называемое «Подготовка», я продолжал получать ошибку диапазона в обновленной модели, которую использовал, следующее:

Код: Выделить всё

import 'package:hive/hive.dart';

class Ingredient {
final String name;
final String quantity;
final String unit;
final String? preparation;

Ingredient({
required this.name,
required this.quantity,
required this.unit,
this.preparation,
});
}

class IngredientAdapter extends TypeAdapter {
@override
final int typeId = 1; // Unique identifier for the adapter

@override
Ingredient read(BinaryReader reader) {
final name = reader.readString();
final quantity = reader.readString();
final unit = reader.readString();
final preparation = reader.readString();

return Ingredient(
name: name,
quantity: quantity,
unit: unit,
preparation: preparation,
);
}

@override
void write(BinaryWriter writer, Ingredient obj) {
writer.writeString(obj.name);
writer.writeString(obj.quantity);
writer.writeString(obj.unit);
writer.writeString(obj.preparation ?? '');
}
}
Итак, я настроил модель и адаптер для ингредиентов и загрузки старых данных и могу заполнить новую подготовку поля:

Код: Выделить всё

import 'package:hive/hive.dart';

class Ingredient {
final String name;
final String quantity;
final String unit;
final String? preparation;

Ingredient({
required this.name,
required this.quantity,
required this.unit,
this.preparation,
});
}

class IngredientAdapter extends TypeAdapter {
@override
final int typeId = 1; // Unique identifier for the adapter

@override
Ingredient read(BinaryReader reader) {
final name = reader.readString();
final quantity = reader.readString();
final unit = reader.readString();
String? preparation;

return Ingredient(
name: name,
quantity: quantity,
unit: unit,
preparation: preparation,
);
}

@override
void write(BinaryWriter writer, Ingredient obj) {
writer.writeString(obj.name);
writer.writeString(obj.quantity);
writer.writeString(obj.unit);
writer.writeString(obj.preparation ?? '');
}
}
Однако, когда я перезапускаю приложение, я получаю сообщение об ошибке RangeError, когда оно пытается прочитать ингредиенты с новым полем приготовления.
Итак, я подумал, что могу создать гибридное решение, чтобы прочитать его, если оно существует, или перейти к нулевому значению, если оно не существует (как указано выше)... используя следующий код:

Код: Выделить всё

import 'package:hive/hive.dart';

class Ingredient {
final String name;
final String quantity;
final String unit;
late String? preparation;

Ingredient({
required this.name,
required this.quantity,
required this.unit,
this.preparation,
});
}

class IngredientAdapter extends TypeAdapter {
@override
final int typeId = 1; // Unique identifier for the adapter

@override
Ingredient read(BinaryReader reader) {
final name = reader.readString();
final quantity = reader.readString();
final unit = reader.readString();
String? preparation;

try {
preparation = reader.readString(); // Try reading the preparation field
} catch (_) {
//String? preparation;
}

return Ingredient(
name: name,
quantity: quantity,
unit: unit,
preparation: preparation,
);
}

@override
void write(BinaryWriter writer, Ingredient obj) {
writer.writeString(obj.name);
writer.writeString(obj.quantity);
writer.writeString(obj.unit);
writer.writeString(obj.preparation ?? '');
}
}
Это привело к HiveError (HiveError: Невозможно прочитать, неизвестный идентификатор типа: 246. Вы забыли зарегистрировать адаптер?).
Мой main. dart оставался довольно последовательным во всем, я где-то читал, что модель, связанная с адаптером, поможет, но это не помогло. Вот основная функция моего приложения:

Код: Выделить всё

void main() async {
await Hive.initFlutter();
Hive.registerAdapter(RecipeAdapter());
Hive.registerAdapter(GroceryAdapter());
Hive.registerAdapter(IngredientAdapter());
Hive.registerAdapter(SettingsModelAdapter());

await Hive.openBox('recipes');
await Hive.openBox('groceries');
await Hive.openBox('settings'); // Open the settings box

ThemeMode initialThemeMode =
await _getInitialThemeModeFromHive() ?? ThemeMode.system;
final initialSortCriteria =
await _getInitialSortCriteriaFromHive() ?? SortCriteria.dateAdded;
final initialSortMethod =
await _getInitialSortMethodFromHive() ?? SortMethod.descending;

if (defaultTargetPlatform == TargetPlatform.android) {
WidgetsFlutterBinding.ensureInitialized();
MobileAds.instance.initialize();
}
runApp(MyApp(
initialThemeMode: initialThemeMode,
initialSortCriteria: initialSortCriteria,
initialSortMethod: initialSortMethod,
));
}
Я не понимаю, как добавить это поле и не нарушить путь обновления, я не хочу очищать данные. Есть идеи?

Подробнее здесь: https://stackoverflow.com/questions/783 ... -new-field
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»