1. 事前準備
本程式碼研究室將說明如何自行建構一款名為「Forage」的新應用程式。本程式碼研究室將引導您逐步完成 Forage 應用程式專案,包括在 Android Studio 中設定和測試專案。
必要條件
- 此專案適用於已完成 Android Kotlin 基本概念課程單元 5 的學員。
建構項目
- 實作實體、DAO、ViewModel 和資料庫類別,以便透過 Room 在應用程式中加入持續性機制。
軟硬體需求
- 已安裝 Android Studio 的電腦。
2. 已完成應用程式總覽
完成後的 Forage 應用程式可讓使用者追蹤他們在自然界中覓得的項目,例如食物。在使用 Room 的工作階段之間會保留此資料。您將運用所掌握的 Room 知識,以及對在資料庫執行讀取、寫入、更新及刪除作業的瞭解,在 Forage 應用程式中實現持續性。下文說明完成後的應用程式及其功能。
應用程式初次啟動時,使用者會看到空白畫面,其中包含顯示覓得項目的回收器檢視畫面,還有右下角可用來新增項目的浮動式按鈕。
新增項目時,使用者可以指定名稱、找到項目的地點,並加上其他附註。你也可以有核取方塊,以指定食品是否屬於當季。
新增的項目將顯示在第一個畫面的回收器檢視畫面中。
輕觸某個項目就會開啟詳細資料畫面,並顯示名稱、地點和附註。
浮動式按鈕也會從加號變更為編輯圖示。輕觸此按鈕即可開啟畫面,以便編輯名稱、地點、附註和「當季」核取方塊。輕觸刪除按鈕則可從資料庫中移除項目。
雖然系統已導入此應用程式的使用者介面部分,但您的任務是運用對 Room 的瞭解來實現持續性,讓應用程式能夠讀取、寫入、更新及刪除資料庫中的項目。
3. 開始操作
下載專案程式碼
請注意,資料夾名稱是 android-basics-kotlin-forage-app
。在 Android Studio 中開啟專案時,請選取這個資料夾。
如要取得這個程式碼研究室的程式碼,並在 Android Studio 中開啟,請按照下列步驟操作:
取得程式碼
- 按一下上面顯示的網址。系統會在瀏覽器中開啟專案的 GitHub 頁面。
- 在專案的 GitHub 頁面中,按一下「Code」按鈕開啟對話方塊。
- 在對話方塊中,按一下「Download ZIP」按鈕,將專案儲存到電腦。等待下載作業完成。
- 在電腦中找到該檔案 (可能位於「下載」資料夾中)。
- 按兩下解壓縮 ZIP 檔案。這項操作會建立含有專案檔案的新資料夾。
在 Android Studio 中開啟專案
- 啟動 Android Studio。
- 在「Welcome to Android Studio」視窗中,按一下「Open an existing Android Studio project」。
注意:如果 Android Studio 已開啟,請依序選取「File」>「New」>「Import Project」選單選項。
- 在「Import Project」對話方塊中,前往解壓縮專案資料夾所在的位置 (可能位於「下載」資料夾中)。
- 按兩下該專案資料夾。
- 等待 Android Studio 開啟專案。
- 按一下「Run」按鈕 即可建構並執行應用程式。請確認應用程式的建構符合預期。
- 在「Project」 工具視窗中瀏覽專案檔案,查看應用程式的設定方式。
4. 設定專案以使用 Room
定義 Forageable 實體
專案已有 Forageable
類別,可定義應用程式的資料 (model.Forageable.kt)。此類別有多個屬性:id
、name
、address
、inSeason
和 notes
。
data class Forageable(
val id: Long = 0,
val name: String,
val address: String,
val inSeason: Boolean,
val notes: String?
)
不過,若要使用此類別儲存持續性資料,就需要將類別轉換為 Room 實體。
- 使用這個表格名稱為
"forageable_database"
的@Entity
為類別加上註解。 - 將
id
屬性設定為主鍵。主鍵應由系統自動產生。 - 將
inSeason
屬性的欄名稱設定為"in_season"
。
實作 DAO
您將透過檢視模型存取資料庫,而 ForageableDao
(data.ForageableDao.kt) 可用來定義從資料庫讀取及寫入資料庫的方法,就如同您的猜像。由於 DAO 只是您定義的介面,因此無需撰寫任何程式碼即可導入這些方法。您應該改用 Room 註解,視需要指定 SQL 查詢。
在 ForageableDao
介面中,您必須新增五個方法。
getForageables()
方法會對資料庫中的所有資料列傳回Flow<List<Forageable>>
。getForageable(id: Long)
方法會傳回符合指定id
的Flow<Forageable>
。insert(forageable: Forageable)
方法會將新的Forageable
插入至資料庫中。update(forageable: Forageable)
方法會採用現有Forageable
作為參數,並據此更新資料列。delete(forageable: Forageable)
方法會採用Forageable
作為參數,然後從資料庫中將其刪除。
導入檢視模型
ForageableViewModel
(ui.viewmodel.ForageableViewModel.kt) 已部分導入,但您必須新增可存取 DAO 方法的功能,才能實際讀取及寫入資料。請按照下列步驟導入 ForageableViewModel
。
- 傳遞
ForageableDao
例項時,應以類別建構函式中參數的形式傳遞。 - 建立
LiveData<List<Forageable>>
類型的變數,此變數會使用 DAO 取得完整的Forageable
實體清單,並將結果轉換為LiveData
。 - 建立採用 ID (
Long
類型) 做為參數的方法,此方法會在 DAO 上呼叫getForageable()
方法,並將結果轉換為LiveData
,藉此傳回LiveData<Forageable>
。 - 在
addForageable()
方法中,使用viewModelScope
啟動協同程式,並使用 DAO 將Forageable
例項插入至資料庫中。 - 在
updateForageable()
方法中,使用 DAO 更新Forageable
實體。 - 在
deleteForageable()
方法中,使用 DAO 更新Forageable
實體。 - 建立可透過
ForageableDao
建構函式參數建立ForageableViewModel
例項的ViewModelFactory
。
導入資料庫類別
ForageDatabase
(data.ForageDatabase.kt
) 類別實際上是將實體和 DAO 公開給 Room。按照說明導入 ForageDatabase
類別。
- 實體:
Forageable
- 版本:
1
- exportSchema:
false
- 在
ForageDatabase
類別中,加入能夠傳回ForageableDao
的抽象函式 - 在
ForageDatabase
類別中,用名為INSTANCE
的私人變數和傳回ForageDatabase
單例模式的getDatabase()
函式定義夥伴模式物件。
- 在
BaseApplication
類別中,建立使用延遲初始化功能傳回ForageDatabase
例項的database
屬性。
5. 保留及讀取片段中的資料
設定實體、DAO、檢視模型,以及定義要在 Room 公開的資料庫類別後,您只需要修改 Fragments,即可存取檢視模型。您必須在三個檔案中進行變更,各檔案用於應用程式中的各畫面。
Forageable 清單
Forageable 清單畫面只需要兩個項目:檢視模型的參照,以及對完整 Forageable 清單的存取權限。在 ui.ForageableListFragment.kt 中執行以下工作。
- 類別中已有
viewModel
屬性。但不使用您在上一個步驟中定義的工廠函式。您必須先重構此宣告,才能使用ForageableViewModelFactory
。
private val viewModel: ForageableViewModel by activityViewModels {
ForageableViewModelFactory(
(activity?.application as BaseApplication).database.foragableDao()
)
}
- 然後在
onViewCreated()
中,從viewModel
觀測allForageables
屬性,並視需要在轉接程式上呼叫submitList()
來填入清單。
Forageable 詳細資料畫面
對於 ui/ForageableDetailFragment.kt 中的詳細資料清單,您需要執行的動作幾乎完全相同。
- 轉換
viewModel
屬性以正確初始化ForageableViewModelFactory
。 - 在
onViewCreated()
中,呼叫檢視模型上的getForageable()
,並傳入id
以取得Forageable
實體。觀測動態資料並將結果設定為forageable
屬性,然後呼叫bindForageable()
來更新使用者介面。
新增及編輯 Forageable 畫面
最後,您需要在 ui.AddForageableFragment.kt 中執行類似操作。請注意,此畫面也會負責更新及刪除實體。不過,系統已從檢視模型的正確位置呼叫這些方法。您只需在此檔案中進行兩項變更即可。
- 再次重構
viewModel
屬性以使用ForageableViewModelFactory
。 - 在您調整刪除按鈕的顯示設定之前,請在
onViewCreated()
的 if 陳述式區塊中,呼叫檢視模型上的getForageable()
,並傳入id
,然後將結果設定為forageable
屬性。
這就是您需要在片段中執行的所有動作。您現在可以執行應用程式,藉此查看動作中的所有持續性功能。
6. 測試指示
執行測試
如要執行測試,請執行下列其中一項動作:
如果是單一測試案例,請開啟測試案例類別 PersistenceInstrumentationTests.kt
,然後按一下類別宣告左側的綠色箭頭。然後,您可以從選單中選取「Run」選項。這麼做將會執行測試案例中的所有測試。
您通常只需要執行一項測試,例如在只有一個測試失敗,而其他測試都通過時。執行單一測試的做法,與執行整個測試案例一樣。使用綠色箭頭並選取「Run」選項。
如果您有多個測試案例,也可以執行整個測試套件。就像執行應用程式一樣,您可以在「Run」選單中找到這個選項。
請注意,Android Studio 會預設為您所執行的最後一個目標 (應用程式、測試目標等),因此如果選單仍顯示「Run」>「Run ‘app'」,您可以依序選取「Run」>「Run」執行測試目標。
然後從彈出式選單中選擇測試目標。