ペットクリニックの実装を解説

今回は、こちらの記事でご紹介したペットクリニックの実装で、キーとなるポイントをいくつか解説させて頂きます。

状態管理で利用しているflutter_riverpod

パッケージはこちらです。
https://pub.dev/packages/flutter_riverpod
画面の状態管理というとちょっとあやふやですが、端的に言うと状況に応じて画面項目を変化させることです。


ownerのタブでボタンを押すとペット登録画面が開きます。画面イメージはこちらです。

その1 簡単な例

ウィジェット全体で、ボタンと選択された日付を表示するテキストがあります。
以下はこのウィジェットのコードの一部です。(全体はこちらのリンクからご覧になれます)

このウィジェットは CosumerWidget を継承しており、第二引数に

ScopedReader
型の関数が渡されます。
StateProvider
watch
することで、このウィジェットでは
DateTime
型の日付を管理することを明示します。
showDatePicker
で ユーザーが選択した
DateTime
を取得した後、nullでなければ、
_watched.state
にその戻り値を設定して、このウィジェットの状態が変化したことを通知しています。
その結果、この
build
メソッドが再び呼ばれて、フォーマットした日付を表示するTextウィジェットが表示されます。

その2 やや複雑な例

まず、このペットクリニックの仕様ですが、タブによってAPIを呼び出すタイミングを変えています。

タブAPIを呼び出すタイミング
owner, petタブを初めて開いたときと、ownerタブやpetタブでデータが変更されたときだけ
veterinarianタブを開くたび
tabs image…

それぞれタブが利用するAPIの呼び出し結果は

Stream
として返すように実装しています。 一覧に表示するデータが画面の状態であり、 StreamProvider を watchすることで、Streamに変化が起きた際にはウィジェットの buildメソッドが実行されるようにしています。 つまり、ownerタブでペットを追加したり、petタブでペットの名前を変更した場合は、ownerとpetのタブのデータを再取得しますが、変更がなければAPIを呼び出さなくて済むようにしています。
実際のアプリでは、タブを開く度に最新のデータが表示されることが望ましいかもしれませんが、今回はあえて任意のタイミングでデータの再取得が行われるようにしています。


それではどうやって実現しているか、コードを見ていきましょう。 ownerタブの

StreamProvider
は以下の箇所で宣言しています。

注目すべきは下から3行目です。

    ref.watch(ownersReloadProvider);

StreamProvider自身が1行目で宣言した別の

StateProvider
をwatchしていますね。(ReloadTriggerというのは今回のサンプルのために作った中身のないクラスです)
<span class="has-inline-color has-vivid-red-color">ownersReloadProvider</span>
は、OwnerTabのdartファイルの中にグローバルで宣言されていて、他のファイルから参照が可能であり、状態を変更することができます。

例えば、petタブでペットの名前を変更するために、サーバーのPUTリクエストを呼び出し、正常に終了した場合は、以下のコードが呼ばれます。

それぞれのタブでグローバルに宣言したプロバイダーの

state
ReloadTrigger
クラスの新しいインスタンスを与えることで、これらを
watch
している
StreamProvider
が、もう一度APIを呼び出してくれるという訳です。
ただし、実際にはタブが開かれる前にAPIが呼び出されることはありません。

一方、veterinarian(獣医)のタブは、タブを開く度にAPIが呼ばれるのですが、これは以下のようにコードを書くことで実現しています。

Veterinarian tab image…

上記のようにStreamProviderのautoDisposeコンストラクタを利用すると、watchしているウィジェットが破棄される(このサンプルの場合は別のタブを開く)と、自動的にこのStreamProvider自身もその状態を破棄します。

それでは長くなりましたので、今回はこのあたりで!

ローカルで動かしながらコードを読んでみたい方は、こちらをどうぞ!