Firebase RTDBのデータをAPIを使って更新するパターンの応答性を保つ
一応モバイルアプリが前提の話。webでも通じる話ではあると思う。
表示:Firebase RTDB (Realtime Database) からデータをStream取得
更新:REST APIを使って更新 → サーバー側でRTDBに反映
この時、アプリ側でローディング表示などもなしに単純にAPIを叩くと、APIリクエスト〜レスポンス+RTDBへの反映のリードタイムで表示上のラグが発生する。
結果、ボタンを押しても即時に反映されないといったことが起こる。これは良くない。
これを解消するためには、ローカルDB( or メモリ上のキャッシュ)を組み合わせるといい。
Riverpodで書くとこんな感じ
code:dart
final baseStream = StreamController<String>.broadcast();
final baseDataSource = StreamProvider.autoDispose(
(_) => baseStream.stream,
);
final fooData = Provider.autoDispose((ref) {
final cacheData = ref.watch(cache);
if (cacheData != null) {
return cacheData;
}
return ref.watch(baseDataSource).valueOrNull ?? 'default';
});
final cache = StateProvider.autoDispose<String?>((ref) => null);
fooData が画面に表示するデータとして、cache が空でないときはそれを表示、そうでないときはRTDBのデータを参照するという風になる。
APIを叩くときは、cache の方を更新しつつ、そのデータを反映するように叩く。
code:dart
Future<void> updateFoo(String data) async {
ref.read(cache.notifier).update((_) => data);
await someApiCall(data);
}
キャッシュを使わずに愚直に表示すると、連続でAPIを叩いたときに古い状態と新しい状態が競合して最終結果が意図しないことになることがあるが、キャッシュを使うことで直近の操作は即時にUIに反映するため、連続で操作をしても(サーバー側でなにか起こらない限りは)それが反映される、ということが期待できる。
あとはモバイルアプリであれば、ローカルDBを活用して、オフラインの間に更新された状態もよしなにサーバーに反映する、みたいな挙動を実現するといった発展ができるはず。