專案:Forage 應用程式

1. 事前準備

本程式碼研究室將說明如何自行建構一款名為「Forage」的新應用程式。本程式碼研究室將引導您逐步完成 Forage 應用程式專案,包括在 Android Studio 中設定和測試專案。

必要條件

  • 此專案適用於已完成 Android Kotlin 基本概念課程單元 5 的學員。

建構項目

  • 實作實體、DAO、ViewModel 和資料庫類別,以便透過 Room 在應用程式中加入持續性機制。

軟硬體需求

  • 已安裝 Android Studio 的電腦。

2. 已完成應用程式總覽

完成後的 Forage 應用程式可讓使用者追蹤他們在自然界中覓得的項目,例如食物。在使用 Room 的工作階段之間會保留此資料。您將運用所掌握的 Room 知識,以及對在資料庫執行讀取、寫入、更新及刪除作業的瞭解,在 Forage 應用程式中實現持續性。下文說明完成後的應用程式及其功能。

應用程式初次啟動時,使用者會看到空白畫面,其中包含顯示覓得項目的回收器檢視畫面,還有右下角可用來新增項目的浮動式按鈕。

3edd87e63c387d88.png

新增項目時,使用者可以指定名稱、找到項目的地點,並加上其他附註。你也可以有核取方塊,以指定食品是否屬於當季。

6c0c739569bb3b4f.png

新增的項目將顯示在第一個畫面的回收器檢視畫面中。

bcc75e60b70320e8.png

輕觸某個項目就會開啟詳細資料畫面,並顯示名稱、地點和附註。

5096995a4921dcac.png

浮動式按鈕也會從加號變更為編輯圖示。輕觸此按鈕即可開啟畫面,以便編輯名稱、地點、附註和「當季」核取方塊。輕觸刪除按鈕則可從資料庫中移除項目。

f8c708fed3dede1a.png

雖然系統已導入此應用程式的使用者介面部分,但您的任務是運用對 Room 的瞭解來實現持續性,讓應用程式能夠讀取、寫入、更新及刪除資料庫中的項目。

3. 開始操作

下載專案程式碼

請注意,資料夾名稱是 android-basics-kotlin-forage-app。在 Android Studio 中開啟專案時,請選取這個資料夾。

如要取得這個程式碼研究室的程式碼,並在 Android Studio 中開啟,請按照下列步驟操作:

取得程式碼

  1. 按一下上面顯示的網址。系統會在瀏覽器中開啟專案的 GitHub 頁面。
  2. 在專案的 GitHub 頁面中,按一下「Code」按鈕開啟對話方塊。

5b0a76c50478a73f.png

  1. 在對話方塊中,按一下「Download ZIP」按鈕,將專案儲存到電腦。等待下載作業完成。
  2. 在電腦中找到該檔案 (可能位於「下載」資料夾中)。
  3. 按兩下解壓縮 ZIP 檔案。這項操作會建立含有專案檔案的新資料夾。

在 Android Studio 中開啟專案

  1. 啟動 Android Studio。
  2. 在「Welcome to Android Studio」視窗中,按一下「Open an existing Android Studio project」

36cc44fcf0f89a1d.png

注意:如果 Android Studio 已開啟,請依序選取「File」>「New」>「Import Project」選單選項。

21f3eec988dcfbe9.png

  1. 在「Import Project」對話方塊中,前往解壓縮專案資料夾所在的位置 (可能位於「下載」資料夾中)。
  2. 按兩下該專案資料夾。
  3. 等待 Android Studio 開啟專案。
  4. 按一下「Run」按鈕 11c34fc5e516fb1c.png 即可建構並執行應用程式。請確認應用程式的建構符合預期。
  5. 在「Project」 工具視窗中瀏覽專案檔案,查看應用程式的設定方式。

4. 設定專案以使用 Room

定義 Forageable 實體

專案已有 Forageable 類別,可定義應用程式的資料 (model.Forageable.kt)。此類別有多個屬性:idnameaddressinSeasonnotes

data class Forageable(
   val id: Long = 0,
   val name: String,
   val address: String,
   val inSeason: Boolean,
   val notes: String?
)

不過,若要使用此類別儲存持續性資料,就需要將類別轉換為 Room 實體。

  1. 使用這個表格名稱為 "forageable_database"@Entity 為類別加上註解。
  2. id 屬性設定為主鍵。主鍵應由系統自動產生。
  3. inSeason 屬性的欄名稱設定為 "in_season"

實作 DAO

您將透過檢視模型存取資料庫,而 ForageableDao (data.ForageableDao.kt) 可用來定義從資料庫讀取及寫入資料庫的方法,就如同您的猜像。由於 DAO 只是您定義的介面,因此無需撰寫任何程式碼即可導入這些方法。您應該改用 Room 註解,視需要指定 SQL 查詢。

ForageableDao 介面中,您必須新增五個方法。

  1. getForageables() 方法會對資料庫中的所有資料列傳回 Flow<List<Forageable>>
  2. getForageable(id: Long) 方法會傳回符合指定 idFlow<Forageable>
  3. insert(forageable: Forageable) 方法會將新的 Forageable 插入至資料庫中。
  4. update(forageable: Forageable) 方法會採用現有 Forageable 作為參數,並據此更新資料列。
  5. delete(forageable: Forageable) 方法會採用 Forageable 作為參數,然後從資料庫中將其刪除。

導入檢視模型

ForageableViewModel (ui.viewmodel.ForageableViewModel.kt) 已部分導入,但您必須新增可存取 DAO 方法的功能,才能實際讀取及寫入資料。請按照下列步驟導入 ForageableViewModel

  1. 傳遞 ForageableDao 例項時,應以類別建構函式中參數的形式傳遞。
  2. 建立 LiveData<List<Forageable>> 類型的變數,此變數會使用 DAO 取得完整的 Forageable 實體清單,並將結果轉換為 LiveData
  3. 建立採用 ID (Long 類型) 做為參數的方法,此方法會在 DAO 上呼叫 getForageable() 方法,並將結果轉換為 LiveData,藉此傳回 LiveData<Forageable>
  4. addForageable() 方法中,使用 viewModelScope 啟動協同程式,並使用 DAO 將 Forageable 例項插入至資料庫中。
  5. updateForageable() 方法中,使用 DAO 更新 Forageable 實體。
  6. deleteForageable() 方法中,使用 DAO 更新 Forageable 實體。
  7. 建立可透過 ForageableDao 建構函式參數建立 ForageableViewModel 例項的 ViewModelFactory

導入資料庫類別

ForageDatabase (data.ForageDatabase.kt) 類別實際上是將實體和 DAO 公開給 Room。按照說明導入 ForageDatabase 類別。

  1. 實體:Forageable
  2. 版本:1
  3. exportSchema:false
  4. ForageDatabase 類別中,加入能夠傳回 ForageableDao 的抽象函式
  5. ForageDatabase 類別中,用名為 INSTANCE 的私人變數和傳回 ForageDatabase 單例模式的 getDatabase() 函式定義夥伴模式物件。
  1. BaseApplication 類別中,建立使用延遲初始化功能傳回 ForageDatabase 例項的 database 屬性。

5. 保留及讀取片段中的資料

設定實體、DAO、檢視模型,以及定義要在 Room 公開的資料庫類別後,您只需要修改 Fragments,即可存取檢視模型。您必須在三個檔案中進行變更,各檔案用於應用程式中的各畫面。

Forageable 清單

Forageable 清單畫面只需要兩個項目:檢視模型的參照,以及對完整 Forageable 清單的存取權限。在 ui.ForageableListFragment.kt 中執行以下工作。

  1. 類別中已有 viewModel 屬性。但不使用您在上一個步驟中定義的工廠函式。您必須先重構此宣告,才能使用 ForageableViewModelFactory
private val viewModel: ForageableViewModel by activityViewModels {
   ForageableViewModelFactory(
       (activity?.application as BaseApplication).database.foragableDao()
   )
}
  1. 然後在 onViewCreated() 中,從 viewModel 觀測 allForageables 屬性,並視需要在轉接程式上呼叫 submitList() 來填入清單。

Forageable 詳細資料畫面

對於 ui/ForageableDetailFragment.kt 中的詳細資料清單,您需要執行的動作幾乎完全相同。

  1. 轉換 viewModel 屬性以正確初始化 ForageableViewModelFactory
  2. onViewCreated() 中,呼叫檢視模型上的 getForageable(),並傳入 id 以取得 Forageable 實體。觀測動態資料並將結果設定為 forageable 屬性,然後呼叫 bindForageable() 來更新使用者介面。

新增及編輯 Forageable 畫面

最後,您需要在 ui.AddForageableFragment.kt 中執行類似操作。請注意,此畫面也會負責更新及刪除實體。不過,系統已從檢視模型的正確位置呼叫這些方法。您只需在此檔案中進行兩項變更即可。

  1. 再次重構 viewModel 屬性以使用 ForageableViewModelFactory
  2. 在您調整刪除按鈕的顯示設定之前,請在 onViewCreated() 的 if 陳述式區塊中,呼叫檢視模型上的 getForageable(),並傳入 id,然後將結果設定為 forageable 屬性。

這就是您需要在片段中執行的所有動作。您現在可以執行應用程式,藉此查看動作中的所有持續性功能。

6. 測試指示

執行測試

如要執行測試,請執行下列其中一項動作:

如果是單一測試案例,請開啟測試案例類別 PersistenceInstrumentationTests.kt,然後按一下類別宣告左側的綠色箭頭。然後,您可以從選單中選取「Run」選項。這麼做將會執行測試案例中的所有測試。

3e640ec727599a6d.png

您通常只需要執行一項測試,例如在只有一個測試失敗,而其他測試都通過時。執行單一測試的做法,與執行整個測試案例一樣。使用綠色箭頭並選取「Run」選項。

8647a76419540499.png

如果您有多個測試案例,也可以執行整個測試套件。就像執行應用程式一樣,您可以在「Run」選單中找到這個選項。

7a925c5e196725bb.png

請注意,Android Studio 會預設為您所執行的最後一個目標 (應用程式、測試目標等),因此如果選單仍顯示「Run」>「Run ‘app'」,您可以依序選取「Run」>「Run」執行測試目標。

90d3ec5ca5928b2a.png

然後從彈出式選單中選擇測試目標。

3b1a7d82a55b5f13.png