Первое время при работе с 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. Надеюсь Вам пригодится мой туториал, спасибо за внимание!
