Я новичок во Флаттере и Дарт, родом из Android.
Android имеет очень хорошую архитектуру абстракции базы данных, которая называется Room Persistence Library . Насколько мне известно, такой архитектуры абстракции базы данных для Flutter не существует, используя шаблоны проектирования MVVM / MVC.
Мое решение состояло в том, чтобы самому создать его версию Dart. Я сделал это в значительной степени после нескольких головных болей, но я не могу заставить LiveData
правильно работать с использованием дженериков.
Я настроил свой класс так:
class LiveData<T> {
...
}
Сейчас когда я хочу вернуть некоторые данные, это может быть Object
или List<Object>
. Я нашел аккуратный взлом, чтобы отличить их от T
:
...
// Parse response
// This checks if the type is an instance of a single entity or a list.
if (entity is T) {
cachedData = rawData.isEmpty ? null : entity.fromMap(rawData.first) as T;
} else {
cachedData = rawData.map((e) => entity.fromMap(e)).toList() as T;
}
...
Проблема заключается во втором блоке:
cachedData = rawData.map((e) => entity.fromMap(e)).toList() as T;
С ошибкой:
- Unhandled Exception: type 'List<Entity>' is not a subtype of type 'List<Vehicle>' in type cast
Тогда возникает вопрос: как я могу привести Entity
к Vehicle
, когда у меня нет доступа к Vehicle
классу. Только его экземпляр присваивается переменной Entity entity
.
Вот фрагмент, демонстрирующий мой доступ к Vehicle
:
final Entity entity;
...assign Vehicle instance to entity...
print(entity is Vehicle) // True
Я пытался использовать .runtimeType
для безрезультатно. Я также думал о разделении LiveData
на два класса, второй - LiveDataList
. Хотя это, кажется, самое простое решение - не допускать ошибок в коде, - это могло бы привести меня к ошибке (плохой каламбур преднамеренный) и сломать довольно симпатичный прямой порт Room.
В качестве временного решения , Я абстрагировал логи сборки c в обобщенную функцию c для передачи LiveData
в конструкторе.
final T Function(List<Map<String, dynamic>> rawData) builder;
И теперь я вызываю это вместо предыдущего кода построить cachedData
.
// Parse response
cachedData = builder(rawData);
С конструктором для LiveData<List<Vehicle>>
, который вызывается при доступе ко всем транспортным средствам в Dao<Vehicle>
:
class VehicleDao implements Dao<Vehicle> {
...
static LiveData<List<Vehicle>> get() {
return LiveData<List<Vehicle>>(
...
(rawData) => rawData.map((e) => Vehicle.fromMap(e)).toList(),
...
);
}
}