2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Firebase】 Realtime Database 初トライ前に知っておくといいかも?な5つの箇所(スクリプト編)

Posted at

概要

androidアプリ ツケ台帳 を作る際にFirebase realtimedatabaseを初めてさわったのですが、
特に詰まった部分を、備忘録かねて初心者的な目線でメモしてみます (スクリプト編)
アプリの解説、過去の投稿は→こちら
Google Play で手に入れよう

DB設計編はそのうち。

解決方法

Firebaseのリスナー内でcontextを参照する場合
this だけでは取得できなかった。8行目のようにcontextの後に @○○Activity の明示が必要。

hogeActivity.kt
        val postListener = object : ValueEventListener {
            override fun onDataChange(dataSnapshot: DataSnapshot) {

                // xmlにて実装したListViewの取得
                val listView = findViewById<ListView>(R.id.list_view)

                // ArrayAdapterの生成
                val adapter = DetailAdapter(this@DelDetailActivity, (mpostlist.tsuke?: mapOf()).toList())

                // ListViewに、生成したAdapterを設定
                listView.adapter = adapter
                
           override fun onCancelled(databaseError: DatabaseError) {}
       }database.child("fuga").addListenerForSingleValueEvent(postListener)

※コピペでやっているとハマりやすい




読み取り時のSnapshotの参照先
できるだけ狭い範囲を指定すべき。
後からセキュリティルールを定める時に困るし、一度に読むデータが多くなるのでユーザが増えると重くなる原因となる。

少なくともルート(下記画像ではdatabase)を参照するのはやめる(セキュリティルールが全く設定できなくなる)。
NG例:database.addListenerForSingleValueEvent(Listener)
よい例:database.child("messages").addListenerForSingleValueEvent(Listener)

これをやるとルート直下のノードを複数読み込みたい場合に困るが、私の場合はリスナーを入れ子にした。下記の場合、3重になっている。その際、リスナー・スナップショットの名前は変えること。
(他にもっといい方法があるかもしれない。。)

hogeActivity.kt
val postListener = object : ValueEventListener {
            override fun onDataChange(dataSnapshot: DataSnapshot) {
                val postListener_teams = object : ValueEventListener {
                    override fun onDataChange(dataSnapshot_teams: DataSnapshot) {
                        val postListener_users = object : ValueEventListener {
                            override fun onDataChange(dataSnapshot_users: DataSnapshot) {

                                // 本文

                            }
                            override fun onCancelled(databaseError: DatabaseError) {}
                        }
                        database.child("Users").addListenerForSingleValueEvent(postListener_users)
                    }
                    override fun onCancelled(databaseError: DatabaseError) {}
                }
                database.child("Teams").child(teamKey).addListenerForSingleValueEvent(postListener_teams)
            }
            override fun onCancelled(databaseError: DatabaseError) {}
        }
        database.child("Posts").child(postKey).addListenerForSingleValueEvent(postListener)




リスナー内スクリプトの実行タイミング
リスナー内のスクリプトは、配置に関わらずリスナー以外のスクリプトがすべて実行された後に実行される。
例:onCreate内に 命令文1→リスナー内命令文→命令文2 の順番で記入されていた場合、実際には
命令文1→命令文2→リスナー内命令文 の順番で実行される。
Firebaseの読み取りは1回限りの場合もリスナーを使わないといけないので実行順に注意が必要。後から読み取りのリスナーを実装するとハマりやすい罠。

対策として、読み取りの命令文だけでなくその前後のスクリプトもまとめてリスナー内に入れていた。




リスナーの種類
特殊な事情がない限り
.addValueEventListener
でなく
addListenerForSingleValueEvent(1回だけ実行して消えるリスナー)
を使うべき。リスナーが残っていて変な挙動をする例がよくある。特に初心者(私を含む)の場合はリスナーを活用した開発は難しいので.addValueEventListenerを原則使うようにしたほうが余計なトラブルがないだろうと思われる。
これはクエリを使ったリスナーでも同様。




TextViewなどの初期値
Firebaseだけの問題ではないかもしれないですが、DBから読み取って表示するデータは画面表示の際に読み込みのラグが発生するためxmlに初期値を入れておくとTextViewがチラついて見栄えが悪いです。

2
3
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
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?