Android-同步Firestore資料
Firestore的一大特色就是能夠使前端(如手機App)與資料庫的資料進行同步。也就是說,一旦有異動,資料庫就會透過「推送(push)」的方式將新的查詢結果送給前端。好處是程式不需主動拉取(pull)新的資料回來。
本文將介紹如何與資料庫進行同步與停止同步。使用的是Kotlin語言。
一、擬定查詢條件
同步資料其實跟查詢很像。查詢是在某個集合(collection)中透過某些條件取回需要的資料,再透過callback程式進行處理,這種行為是一次性的。
然而同步的機制一旦被建立,其callback程式便會在每次Firestore推送新資料回來時就執行一次。
舉例來說,若要指定查詢條件為滿18歲的學生,程式會這麼寫:
db.collection("Students")
.whereGreaterThanOrEqualTo("age", 18)
而後面會有callback方法,也就是像一般查詢時所用的Listener。
二、建立同步機制
使用where方法(有時還會有orderBy、limit等條件)的回傳結果,會是一個「Query」物件。若無特別查詢條件,則會是一個CollectionReference物件。對於以上物件,呼叫get方法會執行一次性的查詢,並可設置callback程式。
至於要建立同步機制的話,則是呼叫「addSnapshotListener」方法:
db.collection("Students")
.addSnapshotListener { querySnapshot, firebaseFirestoreException ->
val students: List<Student> = querySnapshot?.toObjects(Student::class.java) ?: mutableListOf() for (student: Student in students) {
Toast.makeText(applicationContext, student.name, Toast.LENGTH_SHORT).show()
}
}
上面的例子是對學生集合中的文件進行同步,並透過迴圈的方式,將學生資料中的名字顯示在螢幕上。
透過設置SnapshotListener,使得程式能自行「監聽」Firestore。一旦集合中的資料有異動,在Firestore推送資料後,callback程式就會被觸發。新的QuerySnapshop物件中同樣有查詢結果的文件資料。開發者只要設計好處理文件的程式流程,便可達到即時同步資料的效果。
若讀者把練習用的程式寫好並啟動App,會發現程式先進行了一次查詢,也就是初次的同步,因此才會顯示學生名字。
接下來可以在Firestore網頁直接修改資料試試看。
修改完成後,回頭看看App,畫面上又重新顯示一次資料,並帶有修改過後的名字。另外讀者當然也可以新增或刪除文件,屆時集合中所有的資料都會顯示出來。以上就是同步機制的操作。
三、停止同步
上一節的addSnapshotListener方法會回傳一個「ListenerRegistration」物件。可以透過該物件的「remove」方法來停止同步,不再自動更新資料。
為什麼要這樣做呢?原因之一是若根據程式的需求,在適當的時機停止同步,能夠減少網路傳輸量。
另一個原因與筆者自己遇到的Bug有關。假設App有3個Activity,其中的首頁可以前往瀏覽與新增的畫面。當筆者進入瀏覽畫面後離開,再去新增一筆資料,此時瀏覽畫面的SnapshotListener似乎仍在監聽Firestore。隨後導致瀏覽畫面Activity的callback程式發生NullPointer例外(當時是使用Java)。
因此筆者建議,需要同步資料時可將ListenerRegistration設為Activity的全域變數,並在Activity的生命週期方法「onDestroy」中停止同步:
override fun onDestroy() {
super.onDestroy()
listenerRegistration?.remove()
}