👻

【Flutter】データベースisarをRiverpodでどこからでも呼び出せるようにする方法

2022/05/27に公開

最近 flutterを使ってアプリの開発をしています。その際にRiverpodと呼ばれるアプリ内のさまざまなwidgetから変数やメソッドにアクセスするためのライブラリとisarと呼ばれるデータベースにチャレンジしてみました。

その際に初心者ということもあって結構苦労したのでメモを残しておきたいと思います。もしもっといい方法があるよという優しい方いらっしゃいましたらコメントで教えていただけますと幸いです。

めちゃくちゃ参考にさせていただいた記事

Flutterの状態管理ツールをproviderからriverpodに移行しました
providerからriverpodに移行した話の雑感(その内記事にする)
【Flutter】hiveの後継Isarを試してみる

今回検証に使用したコードはgithubにもあげてあります。

自分のホームページでも同じ内容を公開しています(宣伝)

やりたいこと:どこからでもデータベースにアクセスしてデータベース関連のメソッドも使いたい。

今回主に使ったライブラリ

データベース:isar: ^2.5.0
採用理由:いろんなプラットフォームに対応している。せっかくクロスプラットフォームでアプリをつくるのでいろんな環境で使えると嬉しい。sqfliteよりも対応プラットフォームが多かったので選んでみました(多分)。

どこからでもアクセス:flutter_riverpod: ^2.0.0-dev.9
採用理由:なんかよく使われてるみたいだったから

これらを使って投稿をカードで並べていくようなアプリをデモとして作成してみました。
初心者にはなかなか大変な道のりでした。

アプリのイメージ

ポイント1:isarデータベースのインスタンスをmainで作成(main.dart)

以下のコードのようにisarデータベースのインスタンスをmain()内で作成します。
isarをopenするためにはschemaと保存するdirectoryへのpathが必要となります。
pathはgetApplicationSupportDirectory()で取得しています。
今回schemaはpost.dartフォルダ内でPostSchemaとして定義していますが、今回はRiverpodとisarを組み合わせるところに注力したいのでその方法の詳細はisar公式を確認してください。

https://github.com/sciotein/test_riverpod_isar/blob/master/lib/main.dart

ポイント2:isarデータベースのインスタンスをProviderScopeのoverridesであらかじめ作成したプロバイダー(今回はisarProvider)に渡す。

ProviderScopeは普段この中でRiverpodのプロバイダーを使えるようにするという意味で書くのですが今回はさらにoverridesを使うことでインスタンスを用意したプロバイダー(今回はisarProvider)に継承させています。isarProviderはisar_provider.dartファイル内で用意しています。

これでisarProviderとしてisarがref.watch(isarProvider)という形でどこからでも使えるようになりました。

ポイント3:isarデータベースの操作メソッドをまとめたStateNotifireProviderを作成する

StateNotifireProviderとはユーザー操作により変化する状態を管理するためのものみたいです。今回はユーザー操作によりデータベースの状態を変更したり読み出したりするためこれを使っています。

StateNotifierProviderを作るためには不変なStateとStateNotifierが必要となります。今回Stateはpost_service_model.dart内でfreezedパッケージを使って作成しています。状態としてisar, titlelist, datalistを持っています。Stateにデータベースを更新したタイミングで変化する状態を持たせることでデータベースが更新した際にproviderがウィジェットを自動で更新してくれるようになります。

https://github.com/sciotein/test_riverpod_isar/blob/master/lib/post_service_model.dart

StateNotifierにはデータベースを操作するためのメソッドとデータベースの状態を取得して自身のStateを更新するメソッドを入れました。データベースを操作してもisarインスタンス自体には変化がないみたいなので、その他の状態titlelistなどを更新するように_resetPostState();を書くメソッドの最後に置いています。こうすることでデータベースの更新時にウィジェットの更新ができました。

https://github.com/sciotein/test_riverpod_isar/blob/master/lib/isar_provider.dart

作成したStateNotifierProviderを使ってみる

作成したpostStateNotifierProviderを投稿ページ(PostPage)と投稿結果を表示するページ(PostListPage)で使っていきます。

メソッドが使いたい時:ref.watch(プロバイダ名.notifier)を使う

今回投稿ページではデータベースに投稿を追加する機能とデータベースの中身を全て削除する機能を持たせます。そのために先ほど作成したpostStateNotifierProviderのメソッドが使いたいのでWidget build内でfinal postStateNotifier = ref.watch(postStateNotifierProvider.notifier);としメソッドが使いたいところでpostStateNotifier.メソッド名という形で使っています。

https://github.com/sciotein/test_riverpod_isar/blob/master/lib/post_page.dart

状態が使いたい時:ref.watch(プロバイダ名)を使う

リストを表示するページではデータベースの中身を使って状態を表示しています。そのためfinal postState = ref.watch(postStateNotifierProvider);としてpostState.状態名みたいな形で使っています。

https://github.com/sciotein/test_riverpod_isar/blob/master/lib/post_list_page.dart

まとめ

以上どうでしたでしょうか。

正直flutterを初めて数週間しか経ってないですし、まだまだ変なところたくさんあるかと思いますが、とりあえず動かしてみるの精神でやっていきたいと思います。そして問題が見つかり次第頑張って直していきます。

(優しい方、もっといい方法等教えていただけるとすごく嬉しいです。)

Discussion