Первое время при работе с Flutter мне хватало Hive. Быстро, удобно, но возможностей Hive мне стало не хватать. На странице https://pub.dev/packages/hive разработчики посоветовали попробовать Isar и я решила рискнуть. Много звездочек, но он совсем свежий, ошибки не гуглятся, а документация оставляет большие белые пятна.
Я не хочу дублировать тут все шаги, вот тут можно все посмотреть. Скачали -> Создали схему -> Запустили генератор. Четвертый шаг тоже простой, только схему (schemas
) нужно взять из сгенерированного файла. У меня это activity.g.dart. Сразу в этом файле можно посмотреть как называется список ваших объектов.
Я немного затормозила тут и долго не могла понять почему у меня ничего не работает. Оказывается я по правилам английского языка искала activities, а вот генератор создал activitys. Наверное можно как-то его настроить, но я не успела пока так глубоко копнуть, если знаете как его заставить правильно писать автоматически, расскажите мне)
Ну вот и все что есть в быстром старте. Но мне же нужно следить за изменениями, закрыть потом все и конечно следить за уже открытыми экземплярами и не открывать повторно. Вот об этом я и хотела Вам рассказать)
Для того что бы контролировать все из одно места я создам IzarManager, в единственном экземпляреstatic final IzarManager instance = IzarManager._(); IzarManager._();
Теперь мне нужно посчитать, сколько раз я его открыла и закрыла. В дальнейшем у меня будут еще сущности для хранения, поэтому я буду считать каждую отдельно, по имени final Map<String, int> _izarCounter = <String, int>{};
Создадим дженерик функцию для открытия базы данных. Сначала проверяем открыта ли она, если да добавляем в счетчик, если нет открываем.
Future<Isar> _openIsar<T>(String name, CollectionSchema<T> schema) async {
final dir = await getApplicationSupportDirectory();
final izar = Isar.getInstance(name);
if (izar != null && izar.isOpen) {
final count = _izarCounter[name] ?? 1;
_izarCounter[name] = count + 1;
return izar;
}
_izarCounter[name] = 1;
return Isar.open(
schemas: [schema],
directory: dir.path,
name: name,
inspector: true,
);
}
При закрытии точно так же проверяем нужно ли закрыть или обновить счет.
Future<void> closeIsar<T>(Isar izar) async {
if (!izar.isOpen) {
_izarCounter.remove(izar.name);
return;
}
var count = _izarCounter[izar.name] ?? 1;
count -= 1;
_izarCounter[izar.name] = count;
if (count > 0) return;
await izar.close();
}
ну и сам вызов открытия выглядит так
Future<Isar> openActivityDB() async {
return _openIsar('activities', ActivitySchema);
}
Вот так выглядит код для записи в базу данных. Открыли, записали, закрыли.
Future<void> saveInDatabase(activity) async {
final isar = await IzarManager.instance.openActivityDB();
await isar.writeTxn((isar) async {
await isar.activities.put(activity); // insert & update
});
await IzarManager.instance.closeIsar(isar);
}
Но вот с чтением все немного сложнее, потому что у меня данные могут обновиться без перерисовки. Мне нужно открыть базу данных и подписаться на изменения и только потом закрыть.
class ActivitiesWidgetModel extends ChangeNotifier {
var _activities = <Activity>[];
StreamSubscription<void>? streamSubscription;
Future<void> _readActivitiesFromIsar() async {
_activities = await (await _isar).activities.where().findAll();
notifyListeners();
}
void _setup() async {
_isar = IzarManager.instance.openActivityDB();
await _readActivitiesFromIsar();
Stream<void> userChanged = (await _isar).activities.watchLazy();
streamSubscription = userChanged.listen((newResult) {
_readActivitiesFromIsar();
});
}
}
watchLazy помогает нам следить за изменениями и подписаться на стрим. Ну и конечно при уходе со страницы мы должны закрыть все и отписаться от прослушки.
@override
void dispose() async {
streamSubscription?.cancel();
await IzarManager.instance.closeIsar((await _isar));
super.dispose();
}
Пока мне кажется что Isar это действительно просто, работает быстро, много фильтров и легко искать данные. Пока столкнулась только с проблемой параллельного использования нескольких баз данных, но все решаемо. Если возникнут вопросы по коду то рекомендую посетить канал LazyLoad Dart & Flutter на ютубе. Очень детальный и полезный курс, мне очень помог стартовать во flutter. Надеюсь Вам пригодится мой туториал, спасибо за внимание!