techium

このブログは何かに追われないと頑張れない人たちが週一更新をノルマに技術情報を発信するブログです。もし何か調査して欲しい内容がありましたら、@kobashinG or @muchiki0226 までいただけますと気が向いたら調査するかもしれません。

FirebaseのRealtime Databaseを利用してみる 〜その2〜

前回に引き続き、FirebaseのRealtime Databaseについてです。
今回は、前回保存したデータをクライアント上から参照してみます。

Realtime Databaseはその名の通り、データベースに変更があった場合に、それをリアルタイムにクライアントに反映させることができます。今回はその方法について試してみました。

データベース上の要素にアクセスする

データベース上の要素(保存したKey-Valueの組み合わせを示す)へのアクセスは、アクセスしたい要素への参照(DatabaseReferenceクラスのインスタンス)に対してValueEventListenerをセットすることで、コールバックメソッドにて行えます。

前回データを登録したので、現在のデータベースは下図のようになっています。

f:id:uentseit:20160728222737p:plain

とりあえず、"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が呼ばれます。

f:id:uentseit:20160728225400p:plain

子要素にアクセスする

今回でいうと"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に反映されるのはやばいですね、、、
引き続き調査が必要です。