FirebaseのRealtime Databaseを利用してみる 〜その2〜
前回に引き続き、FirebaseのRealtime Databaseについてです。
今回は、前回保存したデータをクライアント上から参照してみます。
Realtime Databaseはその名の通り、データベースに変更があった場合に、それをリアルタイムにクライアントに反映させることができます。今回はその方法について試してみました。
データベース上の要素にアクセスする
データベース上の要素(保存したKey-Valueの組み合わせを示す)へのアクセスは、アクセスしたい要素への参照(DatabaseReferenceクラスのインスタンス)に対してValueEventListenerをセットすることで、コールバックメソッドにて行えます。
前回データを登録したので、現在のデータベースは下図のようになっています。
とりあえず、"email"の要素にアクセスしてみます。
UserData userData = new UserData(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityMyAccountBinding bind = DataBindingUtil.setContentView(this, R.layout.activity_my_account); bind.setUserData(userData); FirebaseDatabase database = FirebaseDatabase.getInstance(); DatabaseReference refEmail = database.getReference("email"); refEmail.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { Log.d("seit", "ValueEventListener#onDataChange"); userData.setEmail(dataSnapshot.getValue(String.class)); } @Override public void onCancelled(DatabaseError databaseError) { Log.d("seit", "ValueEventListener#onCancelled"); // サーバーエラーかもしくはセキュリティとデータべーすルールによってデータにアクセスできない } }); }
11行目で"email"要素への参照(refEmail)を取得し、13行目でrefEmailに対してValueEventListenerをセットしています。
ValueEventListenerは2つのコールバックメソッドを持っています。
onDatgaChangeは、参照している要素に変化があった場合に呼ばれます。引数に渡されるDataSnapshotには、変更があった要素の変更後のKey-Valueが格納されているので、変更後の値を取得することができます。今回のケースでは、17行目の'dataSnapshot.getValue(String.class)'は"email"に紐づく値の"seit2"が返されます。
ここではDataBindingを利用し、要素に変更ががあったタイミングですぐにViewへ反映するようにしています。
onCancelledはセキュリティとデータベースのルール変更によってデータにアクセスできなくなった時に呼ばれます。例えばデータベースのコンソールからルールを以下のように変更してみるとデータベースにアクセスできなくなる(認証情報を持ってないため)のでonCancelledが呼ばれます。
子要素にアクセスする
今回でいうと"Map"や"user"のように、Map型やプロパティを持つクラスのインスタンスをデータベースに保存した場合、"Map"や"user"を親要素として参照することで、親要素に属する要素を子要素として扱うことができます。
親要素を参照しておくことで、子要素に追加・変更・削除などがあった場合にそれらをChildEventListenerによって検知することができます。
DatabaseReference refMap = database.getReference("Map"); refMap.addChildEventListener(new ChildEventListener() { @Override public void onChildAdded(DataSnapshot dataSnapshot, String s) { // 子要素が追加された時に呼ばれる // dataSnapshot : 追加された要素のKey-Value // s:追加された要素の一つ前の要素のkey名 Log.d("seit", "ValueEventListener#onChildAdded"); } @Override public void onChildChanged(DataSnapshot dataSnapshot, String s) { // 子要素に変化があった場合に呼ばれる // dataSnapshot : 変化のあった子要素のKey-Value // s:変化のあった子要素の一つ前の子要素のKey名 Log.d("seit", "ValueEventListener#onChildChanged"); } @Override public void onChildRemoved(DataSnapshot dataSnapshot) { // 子要素が削除された Log.d("seit", "ValueEventListener#onChildRemoved"); } @Override public void onChildMoved(DataSnapshot dataSnapshot, String s) { // 子要素の順番が変化した Log.d("seit", "ValueEventListener#onChildMoved"); } @Override public void onCancelled(DatabaseError databaseError) { // サーバーエラーかもしくはセキュリティとデータべースルールによってデータにアクセスできない Log.d("seit", "ValueEventListener#onCancelled"); } });
ちなみに、Firebaseのコンソールから直接データの追加や変更、削除を行うことができるので、各種コールバックメソッドが呼ばれることを確認してみるといいでしょう。
※子要素の順番の変更だけ方法がわかりませんでした。クライアントから行う必要がありそうです。
それにしてもデータベースの変更がリアルタイムにViewに反映されるのはやばいですね、、、
引き続き調査が必要です。