LoginSignup
2
1

More than 5 years have passed since last update.

Firebase RTDB で同じパスに対する Listen 時の注意

Last updated at Posted at 2018-02-20

使用したライブラリは以下のバージョン。

implementation "com.google.firebase:firebase-core:11.8.0"
implementation "com.google.firebase:firebase-database:11.8.0"

概要

データベース(のパス)に読み取りアクセス権がない場合、登録したリスナの onCancelled() が呼ばれるが、orderBy を指定してリスナを設定したあと、同じパスに orderBy を指定せずに別のリスナを設定すると、orderBy を指定したリスナには onCancelled() がコールバックされるが、指定しないリスナの onCancelled() は呼ばれない。

バグのようだったので、いずれ直るかもしれません。

検証

ログを出力するだけの LogValueEventListenerLogChildEventListener を用意し、以下のようなコードを書いてみる。

val ref = FirebaseDatabase.getInstance().getReference("test")
ref.orderByKey().addListenerForSingleValueEvent(LogValueEventListener("single-order"))
ref.addListenerForSingleValueEvent(LogValueEventListener("single"))
ref.orderByKey().addValueEventListener(LogValueEventListener("value-order"))
ref.addValueEventListener(LogValueEventListener("value"))
ref.orderByKey().addChildEventListener(LogChildEventListener("child-order"))
ref.addChildEventListener(LogChildEventListener("child"))

同じパスに6つのリスナを登録しているが、onCancelled() が呼ばれたのは orderByKey() を指定した3つのみ。orderByKey() を指定しなかったリスナの onCancelled() は呼ばれなかった。

先頭を orderByKey() なしにしてみる。(2行めと3行めを入れ替え)

val ref = FirebaseDatabase.getInstance().getReference("test")
ref.addListenerForSingleValueEvent(LogValueEventListener("single"))
ref.orderByKey().addListenerForSingleValueEvent(LogValueEventListener("single-order"))
ref.orderByKey().addValueEventListener(LogValueEventListener("value-order"))
ref.addValueEventListener(LogValueEventListener("value"))
ref.orderByKey().addChildEventListener(LogChildEventListener("child-order"))
ref.addChildEventListener(LogChildEventListener("child"))

この場合はすべてのリスナで onCancelled() が呼ばれた。

あとからパーミッションがなくなった場合

addValueEventListener() または addChildEventListener() で登録したリスナに対しては、onDataChanged() などのイベントが通知された後で、パーミッションがなくなった場合も onCancelled() が呼ばれる。

しかし addListenerForSingleValueEvent() はワンショットなので、 onDataChanged() が呼ばれた後は onCancelled() は呼ばれない。

最初に登録したリスナが orderBy ありの addListenerForSingleValueEvent() で、その他が orderBy なしだけの場合、

val ref = FirebaseDatabase.getInstance().getReference("test")
ref.orderByKey().addListenerForSingleValueEvent(LogValueEventListener("single-order"))
ref.addValueEventListener(LogValueEventListener("value"))
ref.addChildEventListener(LogChildEventListener("child"))

いずれのリスナの onCancelled() も呼ばれず、パーミッションエラーになったことに気づくことができなかった。

その後

パーミッションエラーになった後、さらにリスナを登録した場合、もう orderBy ありだろうがなしだろうが何も通知されなくなってしまった。

登録済みのリスナをすべて removeEventListener() で解除したらこの現象は直った。

しかし、addListenerForSingleValueEvent() で登録したリスナは解除する方法がないので、復旧できない。この場合はアプリを終了するしかない気がする。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1