整合 Android Paging Library: Part 2

上一篇 Part 1 講解 Paging 單純使用 Remote 當作資料來源後,我們這篇要來講解另一種常見的資料架構:Remote + Local,我們會先從 Remote 拉資料到 Local 端,然後 App 統一使用 Local 當作資料來源,讓我們來看看是如何實作這樣的資料架構。 

Remote + Local 資料架構

首先我們展示如何拉 Remote 資料到 Local 後,再讓 View 統一用 Local 資料顯示,這邊先不含 Paging 整合,只看一般資料如何從 Remote → Local → View 這樣的流程顯示出來,熟悉這流程後,再來看 Paging Library 是如何支援這樣的資料架構。 Remote 就是我們一般常用的 API,而 Local 我們選用 Room 當作資料庫,採用 MVVM + RxJava 這樣的 Reactive 架構,如果你不熟悉 Android Room 資料庫,可以參考我之前寫的 Room 入門介紹

我們沿用 Part 1. 的顯示貼文動態牆作為講解範例,我們會拉訊息回來存到資料庫,然後讓 View 訂閱資料庫的資料。

架構設計

我們會採用 MVVM 當作 App 架構,Room 本身也支援 Paging,所以我們會採用 Paging + RxJava + Room 來實作,架構和資料流如下圖:

藍線呈現資料流訂閱的狀態,View 訂閱 ViewModel,ViewModel 訂閱 Model,Model 觸發 Remote DataSource 去載入資料回來存到 Local DataSource,最後紅線呈現在資料流訂閱 onNext(Post) 方法被觸發得到新資料:

首先是我們的 Entity class,用來儲存 API 以及資料庫的資料類別:

再來是 ApiService 和 Dao:

最後是 Repository,裡面要實作從 Remote 拉資料回來後寫入 Local 的邏輯,這邊我們提供兩個方法,一個是 getFeeds(),這個方法回傳 Observeable 可以讓其他人訂閱資料流,另一個是 fetchFeeds() 這個會去拉 Remote 資料然後寫入 Local,這個方法是回傳 Completable,完成資料更新後就 complete,因為當資料寫到 Local的時候,getFeeds() 就會自動發出資料變更的通知。(Room 幫我們實作了發出資料變更的通知)

原理介紹

上述的流程熟悉後,換套用 Paging 就會很快上手,我們會向資料庫要資料,當資料庫有資料的時候,可以直接回傳顯示,當所有資料都已經回傳、沒新的資料可以顯示的時候,就需要向 Remote 拉新分頁的資料回來,寫入資料庫,再讓資料庫回傳給介面顯示。 這就是 Paging 實作 Remote + Local 資料來源的原理。

那我們要如何實作這樣的流程呢?Paging有一個關鍵元件可以達成: PagedList.BoundaryCallback,這個抽象類別可以實作兩個方法:

  • onZeroItemsLoaded(): 當 Local 完全沒有任何資料時會觸發,這邊通常都是要實作向 Remote 拉第一個分頁資料寫回 Local 的邏輯。
  •  onItemAtEndLoaded():當 Local 的資料都回傳完了,已經沒有更多資料可以顯示的時候會觸發,這邊通常都是實作向 Remote 拉下一頁資料寫回 Local 的邏輯。

介紹完這元件後,讓我們來實作這 Callback 然後整合到我們的上面 Remote → Local → View 實作內。

實作

再來,要把這個 BoundaryCallback 整合到我們的現有程式內,DAO 和 Repository 都要做相對應的改變。

DAO 要把列表查詢的方法 getPostList() 回傳值改為 DataSource.Factory<String, Post>,Room 底層的實作就已經支援分頁,所以可以直接回傳 DataSource.Factory。

Repository 要把 DataSource 換成 Local 的資料來源 ( getPostList(): DataSource.Factory<Int, Post>,然後在 RxPagedListBuilder()裡面把 BoundaryCallback 加入。

其他 ViewModel 和 View 的部分皆不需要更動,可以直接使用 Remote + Local 的 Paging 資料來源。我們的方法觸發順序和資料流的流向如下:

總結

當我們實作 Paging 資料架構從 Remote 轉換為 Remote + Local 的時候,我們只需要實作 BoundaryCallback、新增 Room DAO 回傳 DataSource.Factory 的方法作為 Local DataSource 的主要資料來源即可,而如果你是採用 MVVM(推薦採用這架構),則 View 和 ViewModel 原本實作的 Paging 邏輯則不需要做任何改動。


Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Blog at WordPress.com.

Up ↑