iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 29
0

今天要使用 Firebase 提供的資料庫功能來存放資料
首先開啟一個空白的專案
然後在 IDE 上方的選單選擇 Tools -> Firebase

接著畫面右邊會彈出選單,選擇 Realtime Database

按下 Save and retrieve data

這邊有兩個基本動作要做,首先是連接到 Firebase
第一次連接時有跳出連接失敗訊息,但似乎還是有連接上,再重按一次會跳出同步訊息,再按同步就可以了

第二步是把相關的 package 加到專案之中,按下按鈕後 IDE 會幫我們自動加入

自動加入的版本會比較舊,可以到 build.gradle 中手動更新

implementation 'com.google.firebase:firebase-database:16.0.5'

綁定和設置完成後就可以在 Firebase Console 中看到自己的專案
點擊進入之後,可以看到畫面 package 名稱後面有一個小紅點

按下後選擇繼續設定 sdk,然後下載它提供的 json 檔案並放到提示的路徑之中
(專案目錄/app 底下,可能需要關掉 IDE 才能覆蓋檔案)

下一步的 gradle 設定跟 IDE 幫我們帶入的大致相同,但是多一行

implementation 'com.google.firebase:firebase-core:16.0.5'

不知什麼原因,從 IDE 設定並沒有帶入這一行

最後在手機上執行過一次 APP,就可以驗證是否安裝成功了。

儲存資料到雲端資料庫

再來要寫程式把資料儲存到 Firebase 上,先到網頁上的控制台新增資料庫
我們這次使用的是 Realtime Database,要注意別選錯

資料庫建立起來之後,回到 MainActivity
首先建立三個會使用到的變數

  • fireDB 存放 FirebaseDatabase 的實體
  • dbRef 存放參考 Firebase 資料庫的節點
  • list 存放資料庫撈下來的資料
private var fireDB = FirebaseDatabase.getInstance()
private var dbRef: DatabaseReference = fireDB.getReference("Users")
private var list: MutableList<User> = mutableListOf()

在 Realtime Database 中是用偵聽的方式去接收資料
首先寫一個方法來處理 addListenerForSingleValueEvent
這個方法只會執行一次而且是立即執行
覆寫 onDataChange 事件可以得到目前資料庫上的資料
把它取出來後轉型,再放到我們處理資料的 list 中
然後顯示在畫面上

private fun setSingleValueEvent() {
    dbRef.addListenerForSingleValueEvent(object : ValueEventListener {
        override fun onCancelled(p0: DatabaseError) {}

        override fun onDataChange(dataSnapshot: DataSnapshot) {
            if (dataSnapshot.exists()) {
                for (item in dataSnapshot.children) {
                    val user = item.getValue(User::class.java)
                    list.add(user!!)
                }
                show()
            }
        }
    })
}

下一步是處理子節點的偵聽
這邊關注新增和刪除的部分
一樣是偵測到新增的時候,會觸發 onChildAdded ,再把得到的值從雲端存到我們的 list 中,再刷新畫面。

刪除一樣,在偵測到刪除節點的時候,會觸發 onChildRemoved ,這裡使用 lambda 去找出那個擁有那個 uid 的 user,然後從 list 中移除,刷新畫面。

private fun setChildEvent() {
    dbRef.addChildEventListener(object : ChildEventListener {
        override fun onCancelled(p0: DatabaseError) {}

        override fun onChildMoved(p0: DataSnapshot, p1: String?) {}

        override fun onChildChanged(p0: DataSnapshot, p1: String?) {}

        override fun onChildAdded(p0: DataSnapshot, p1: String?) {
            val user = p0.getValue(User::class.java)
            list.add(user!!)
            show()
        }

        override fun onChildRemoved(p0: DataSnapshot) {
            val user = p0.getValue(User::class.java)
            list.remove(list.first { x -> x.uid == user!!.uid })
            show()
        }

    })
}

按鈕事件的處理

顯示資料,單純把 list 中的資料放到 TextView

private fun show() {
    var txt = ""
    for (user in list) {
        txt += "${user.name} ${user.age} ${user.tel}\n"
    }
    textView.text = txt
}

新增按鈕按下時,新增一個我們自訂的 User 類別 (這邊寫固定資料,只展示效果)
再利用 DatabaseReference.child 找到節點,然後給值
這邊給值之後,網路上的資料有變動,就會觸發上面設定的 onChildAdded 事件

private fun add() {
    val uid: String = UUID.randomUUID().toString()
    val user = User(uid, "Ben", "15", "01234")
    dbRef.child(uid).setValue(user)
}

這邊直接做移除全部的資料
一樣是透過 DatabaseReference 移除某個節點
每個節點被移除時就會觸發上面設定的 onChildRemoved 事件

private fun clearAll() {
    for (user in list) {
        dbRef.child(user.uid).removeValue()
    }
}

附上 onCreate 方法

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    setSingleValueEvent()
    setChildEvent()

    add.setOnClickListener { add() }
    clear.setOnClickListener { clearAll() }
}


上一篇
Day 28 GoogleMap Polygons
下一篇
Day 30 Firebase Cloud Firestore
系列文
Kotlin and Android 30 days30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
wcas
iT邦新手 5 級 ‧ 2018-11-29 13:58:34

不好意思,我再匯入firebase的時候一直出現錯誤

我用的是android8.0和7.1.1兩個都不行

https://ithelp.ithome.com.tw/upload/images/20181129/20110151fllvjgr56u.jpg

我有看到國外的論壇說的是版本衝突,我也試了很多次都是一樣

請問有什麼方法解決嗎?

謝謝

River iT邦新手 5 級 ‧ 2018-11-29 22:57:12 檢舉

dependencies 中最下方 firebase-database 版本改成:
implementation 'com.google.firebase:firebase-database:16.0.5' 試看看

我要留言

立即登入留言