スマホアプリ開発を加速する,Firebaseを使ってみよう

第3回 データの読み出しをマスターする

この記事を読むのに必要な時間:およそ 11 分

Child Changedイベント

Child Changedイベントは,配列のようなデータ構造で,要素に更新があるごとに呼び出されます。

Child Changedイベントは,ChildEventListenerインタフェースのonChildChanged(DataSnapshot snapshot, String previousChildKey)をオーバーライドすることで受信することができます。

onChildChangedの第一引数のDataSnapshotは,更新された要素そのものになります。

ソースコードは,Child Addedのサンプルコードの5行目がonChildChanged(DataSnapshot dataSnapshot, String previousKey)になる以外はまったく同じです。

実装後,WebコンソールからsenderJohnからJackに変えてみてください。

ログにJackの情報だけが出力されれば成功です。

D/Firebase: onChildChanged, sender:Jack, body:Hi, there!

Child Removedイベント

Child Removedイベントは,配列のようなデータ構造で,要素が削除されるごとに呼び出されます。

Child Removedイベントは,ChildEventListenerインタフェースのonChildRemoved(DataSnapshot snapshot)をオーバーライドすることで受信することができます。

onChildRemovedの引数のDataSnapshotは,削除された要素そのものになります。

こちらもソースコードは,Child Addedのサンプルコードの5行目がonChildRemoved(DataSnapshot dataSnapshot)になる以外はまったく同じです。

実装後,WebコンソールからsenderJackのチャットメッセージを削除してみてください。

以下のように削除されたJackのメッセージがログに出力されれば成功です。

D/Firebase: onChildRemoved, sender:Jack, body:Hi, there!

Child Movedイベント

Child Movedイベントは,配列のようなデータ構造で,要素が移動されるごとに呼び出されます。

Child Movedイベントは,ChildEventListenerインタフェースのonChildMoved(DataSnapshot snapshot, String previousKeyをオーバーライドすることで受信することができます。

onChildMovedの第一引数のDataSnapshotは,移動された要素そのものになります。

こちらもソースコードは,Child Addedのサンプルコードの5行目がonChildMoved(DataSnapshot dataSnapshot, String previousKey)になる以外はまったく同じです。

Childe Movedイベントは,ソート済みデータの一部に変更があり,順番の並び替えが発生した場合に呼び出されます。データのソートに関しては本連載の後半について解説します。

イベントに関する保証

Firebaseではイベントの通知順について以下の保証があります。

  1. 必ずデータベースのローカルコピーに最初に状態を反映する
  2. 一時的にローカルコピーとリモートのデータベースの状態が食い違ったとしても,最終的にきちんと同期される
  3. ローカルコピーの変更はリモートに書き込まれ,完了後に全クライアントにブロードキャストされる
  4. Valueイベントは必ず最後に呼び出され,その引数で渡されるDataSnapshotにはこれまでの変更がすべて含まれていることが保証される

Firebaseではデータベースのローカルコピーをクライアント側に持つため,オフライン状態でも問題なくデータの読み書きができることを連載第1回で述べました。

このため,まずはローカルにデータが書き込まれ,それから中央のデータベースに変更が反映されます。その後,同じデータベースを参照している各クライアントに変更が通知され,最終的にはすべての環境で同じ状態に収束します。

また,先ほどの/messagesの例のように,ひとつのURIに複数のリスナを登録することができますが,その場合でもValueイベントは必ず一番最後に呼び出され,一連の変更がすべて反映されたDataSnapshotが入っていることが保証されています。あまり同一URIに複数のリスナを登録するケースは多くはないかも知れませんが,頭の片隅に覚えておくと良いかもしれません。

リスナの登録解除

登録したリスナは,ref.removeEventListener(originalListener)で解除することができます。

もし複数のリスナを登録している場合は,不要になった際に登録した分だけ解除してください。リスナを適切に解除しないと,意図しないイベントコールバックが発生したり,メモリリークにつながる恐れがあります。

一点注意点として,上位のURIでリスナを登録解除したからといって,それ以下のすべてのリスナを解除したということにはなりませんので注意してください。

ワンショットのValueイベントリスナ

一度だけデータを取得するのに使って以後変更があっても利用しないようなケースでは,addListenerForSingleValueEvent()ValueEventListenerを登録するのが便利です。

ref.addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot snapshot) {
        // do some stuff once
    }
    @Override
    public void onCancelled(FirebaseError firebaseError) {
    }
});

以上のようにすると,初回のみ指定したURI以下の全データを取得し,そのままリスナを登録解除してくれます。

著者プロフィール

白山文彦(しろやまふみひこ)

サーバサイド,インフラ,Androidなど何でもやるプログラマ。