Как добавить Isar в проект на Flutter

от автора

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


ссылка на оригинал статьи https://habr.com/ru/post/673068/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *