Android-同步Firestore資料

Vincent Zheng
新手工程師的程式教室
4 min readJan 5, 2019

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網頁直接修改資料試試看。

在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()
}

--

--

Vincent Zheng
新手工程師的程式教室

我是Vincent,是個來自資管系的後端軟體工程師。當初因為學校作業,才踏出寫部落格的第一步。這裡提供程式教學文章,包含自學和工作上用到的經驗,希望能讓讀者學到東西。我的部落已搬家至 https://chikuwa-tech-study.blogspot.com/