iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 30
0
自我挑戰組

Kotlin and Android 30 days系列 第 30

Day 30 Firebase Cloud Firestore

昨天使用了 Firebase 的 Realtime Database 功能
今天試著使用另一個資料庫 Firebase Cloud Firestore

綁定動作大致與上一篇都相同,這次選擇 Firestore,然後一樣照步驟連接資料庫和加入 package 到 gradle

build.gradle 中一樣要加入 implementation 'com.google.firebase:firebase-core:16.0.5'

Dex Error

在設定完成後,執行 App ,卻發現報錯
Error: Cannot fit requested classes in a single dex file

查詢後發現是因為專案參考到的方法不能超過 65,536 個,65536 = 64 X 1024,這個問題也被稱為 64K reference limit

在 Android 版本 5.0 (API LEVEL 21) 之前,Android 是在 Dalvik runtime 上執行程式碼,而 Dalvik 預設會限制一個 APK 檔案對應一個 .dex 檔案

解決方法:在 build.gradle 中加入

defaultConfig {
    ...
    multiDexEnabled true
}


dependencies {
    ...
    implementation 'com.android.support:multidex:1.0.3'
}

附上 官方說明

讀取資料

collection 裡面放節點名稱
而要取回資料一樣透過 .addOnCompleteListener 中的 task.result 去得到資料集合
並逐一轉型成我們要的 User 類別,然後存到 list 中

private fun load() {
    firestore.collection("Users")
        .get()
        .addOnCompleteListener { task ->
            if (task.isSuccessful) {
                for (document in task.result!!) {
                    list.add(document.toObject(User::class.java))
                }
                show()
            } else {
                println(task.exception?.message!!)
            }
        }
}

新增資料

Cloud Firestore 新增資料需要給它 HashMap 的形式
這裡設定一個 HashMap<String, String> ,Key 是字串,也就是我們的欄位;value 是值,因為我們這裡值都是字串所以型別用 String
假設今天有多種型別的值(假設 age 是 Int),則可以使用 HashMap<String, Any>

private fun add() {
    val uid: String = UUID.randomUUID().toString()
    val data: HashMap<String, String> = hashMapOf()

    val user = User(uid, "Ben", "18", "51236463")

    data["uid"] = user.uid
    data["name"] = user.name
    data["age"] = user.age
    data["tel"] = user.tel

    firestore.collection("Users")
        .document(uid)
        .set(data)
        .addOnSuccessListener {
            list.add(user)
            show()
        }
        .addOnFailureListener { e ->
            println(e.message)
        }
}

清除資料

刪除資料一樣是找 User 節點底下的某一個節點,然後刪除
成功刪除後把 list 裡面的同一個 User 也刪除掉,接著刷新畫面

private fun clearAll() {
    for (user in list) {
        delete(user.uid)
    }
}

private fun delete(uid: String) {
    firestore.collection("Users").document(uid).delete()
        .addOnSuccessListener {
            val user = list.first { x -> x.uid == uid }
            list.remove(user)
            show()
        }
        .addOnFailureListener { e ->
            println(e.message)
        }
}

一樣會有個 show() 方法來顯示資料

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

後記

在測試過程中,遇到一個問題就是如果使用 5.0 以下的版本測試, Cloud Firestore 在做新增移除時會沒有作用;查詢後可能是因為在舊版本的手機中,安全協定的版本比較舊,然後 Firestore 的版本比較新,那 SSL 可能就會發生錯誤。
可能可以嘗試更換 Firestore 的版本到比較舊的版本,待測試。


上一篇
Day 29 Firebase Realtime Database
系列文
Kotlin and Android 30 days30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言