本程式碼研究室是 Android Kotlin 基礎課程的一部分。使用程式碼研究室逐步完成程式碼課程後,您將能充分發揮本課程的潛能。所有課程程式碼研究室清單均列於 Android Kotlin 基礎程式碼研究室到達網頁。
引言
大部分應用程式都有需要保留的資料,就算使用者關閉應用程式也一樣。例如,應用程式可能會儲存播放清單、遊戲項目清單、開銷和收入記錄、系列作品目錄或長期資料。您通常會使用資料庫儲存永久資料。
Room
是屬於 Android Jetpack 的資料庫程式庫。Room
負責設定及設定資料庫的眾多工作,而且可以讓您的應用程式透過一般的函式呼叫與資料庫互動。實際上,Room
是 SQLite 資料庫頂端的抽象層。Room
套用 SQL 模型時,採用術語和查詢語法即可進行更複雜的查詢。
下圖顯示 Room
資料庫如何與本課程中建議的整體架構配合使用。
須知事項
您應該很熟悉:
- 為 Android 應用程式建立基本使用者介面 (UI)
- 使用活動、片段和視圖。
- 在片段之間瀏覽,並使用安全引數 (Gradle 外掛程式) 在片段之間傳送資料。
- 查看模型、檢視模型工廠、
LiveData
及其觀測器。本課程的先前程式碼研究室涵蓋這些架構元件主題。 - 對 SQL 資料庫和 SQLite 語言有基本瞭解。如需快速總覽或重新整理重點,請參閱 SQLite Primer。
課程內容
- 如何建立
Room
資料庫並進行互動,藉此保留資料。 - 如何建立資料類別以定義資料庫中的資料表。
- 如何使用資料存取物件 (DAO) 將 Kotlin 函式對應至 SQL 查詢。
- 如何測試資料庫是否正常運作。
執行步驟
- 建立具有夜間睡眠資料的介面的
Room
資料庫。 - 使用提供的測試來測試資料庫。
在這個程式碼研究室中,您將建構追蹤睡眠品質的應用程式資料庫部分。應用程式會使用資料庫儲存一段時間內的睡眠資料。
這個應用程式有兩個畫面,以片段表示,如下圖所示。
第一個畫面 (如左側所示) 為開始和停止追蹤的按鈕。畫面會顯示使用者的睡眠資料。[清除] 按鈕永久刪除應用程式已收集的所有資料。
第二個螢幕則是根據選取睡眠品質評分的方式。在應用程式中,評分是以數字表示。在開發方面,應用程式會同時顯示臉部圖示和對應的數值。
使用者流程如下:
- 使用者開啟應用程式並顯示睡眠追蹤畫面。
- 使用者輕觸 [開始] 按鈕。這會記錄開始時間,並顯示。[開始] 按鈕已停用,[停止] 按鈕也已啟用。
- 輕觸 [停止] 按鈕。這會記錄結束時間,並開啟睡眠品質畫面。
- 使用者選取睡眠品質圖示。螢幕會關閉,追蹤畫面會顯示睡眠的結束時間和睡眠品質。[停用] 按鈕已停用,且 [開始] 按鈕已啟用。應用程式已可繼續進行其他夜晚,
- 如果資料庫中有資料,[清除] 按鈕就會啟用。使用者輕觸 [清除] 按鈕時,系統會將他們的所有資料清除,而不會經過清除,不會出現「你同意升級」的訊息。
此應用程式使用簡易架構,如下圖所示,在完整架構的情境中。應用程式僅使用下列元件:
- UI 控制器
- 檢視模型及
LiveData
- 會議室資料庫
步驟 1:下載並執行啟動應用程式
- 從 GitHub 下載 TrackMySleepquality-Starter 應用程式。
- 建構並執行應用程式。應用程式會顯示
SleepTrackerFragment
片段的使用者介面,但沒有資料。這些按鈕不會回應輕觸。
步驟 2:檢查啟動應用程式
- 查看 Gradle 檔案:
- 專案 Gradle 檔案
在專案層級的build.gradle
檔案中,您會看到指定程式庫版本的變數。不論是透過入門應用程式使用的版本,皆可和這個應用程式搭配使用,而且可與這個應用程式搭配運作。在完成這個程式碼研究室之後,Android Studio 可能會提示您更新部分版本。您需要自行決定是否要更新或繼續使用應用程式中的版本。如果您遇到「編譯範圍」錯誤,請嘗試使用最終解決方案應用程式所使用的程式庫版本組合。 - 模組 Gradle 檔案。請注意,您針對所有 Android Jetpack 程式庫提供的依附元件 (包括
Room
) 和協同程式的依附元件。
- 查看套件和 UI。應用程式依功能分類。這個套件包含預留位置檔案,您將在這個系列程式碼研究室中新增程式碼。
database
套件 (適用於Room
資料庫的所有程式碼)。sleepquality
和sleeptracker
套件包含每個畫面的片段、檢視模型和檢視模型工廠。
- 請查看
Util.kt
檔案,其中提供的功能可協助顯示睡眠品質資料。部分程式碼參照了你稍後建立的檢視模型,因此已加上註解。 - 請查看 androidTest 資料夾 (
SleepDatabaseTest.kt
)。您將使用此測試來確認資料庫是否正常運作。
在 Android 中,資料會以資料類別表示,並且可透過函式呼叫存取及修改資料。但在資料庫世界中,您需要實體和查詢。
- 「實體」代表儲存在資料庫中的物件或概念,及其屬性。實體類別定義了資料表,而該類別的每個例項代表表格中的一個資料列。每個屬性都會定義一個資料欄。在您的應用程式中,這個實體將保存有關夜間睡眠的資訊。
- 「查詢」是指對資料庫資料表或資料表組合提出資料/資訊的要求,或對資料執行動作的要求。常見的查詢包括取得、插入及更新實體。例如,您可以查詢記錄的所有睡眠夜晚,並按開始時間排序。
Room
會盡力將 Kotlin 資料類別的資料儲存到可儲存在 SQLite 資料表的實體,以及從函式宣告到 SQL 查詢的困難。
您必須將每個實體定義為加註的資料類別,並將互動定義為註解的介面 (即資料存取物件 (DAO))。Room
會使用這些加註的類別,在資料庫中建立資料表,以及對資料庫執行的查詢。
步驟 1:建立 SleepNight 實體
在這項工作中,您將一晚的睡眠定義為註解的資料類別。
您每晚的睡眠時間必須記錄開始時間、結束時間和品質。
你需要有一組 ID,可用於識別自己的夜間睡眠情況。
- 在
database
套件中,找到並開啟SleepNight.kt
檔案。 - 建立
SleepNight
資料類別,其中包含 ID、開始時間 (以毫秒為單位)、結束時間 (毫秒) 及數值品質評分等參數。
- 您必須初始化
sleepQuality
,因此將其設定為-1
,代表您尚未收集任何品質資料。 - 您也必須初始化結束時間。將開始時間設為開始時間,表示尚未記錄任何結束時間。
data class SleepNight(
var nightId: Long = 0L,
val startTimeMilli: Long = System.currentTimeMillis(),
var endTimeMilli: Long = startTimeMilli,
var sleepQuality: Int = -1
)
- 在類別宣告之前,請以
@Entity
為資料類別加上註解。將資料表命名為「daily_sleep_quality_table
」。tableName
的引數為選用,但建議使用。您可以在說明文件中查詢其他引數。
如果系統顯示提示,請從「androidx
」程式庫匯入「Entity
」和所有其他註解。
@Entity(tableName = "daily_sleep_quality_table")
data class SleepNight(...)
- 要將
nightId
標識為主鍵,請為nightId
屬性加上註解@PrimaryKey
。將autoGenerate
參數設為true
,以便Room
為每個實體產生 ID。這樣可以保證每晚的 ID 不得重複。
@PrimaryKey(autoGenerate = true)
var nightId: Long = 0L,...
- 為其餘屬性加上註解
@ColumnInfo
。使用參數自訂屬性名稱,如下所示。
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "daily_sleep_quality_table")
data class SleepNight(
@PrimaryKey(autoGenerate = true)
var nightId: Long = 0L,
@ColumnInfo(name = "start_time_milli")
val startTimeMilli: Long = System.currentTimeMillis(),
@ColumnInfo(name = "end_time_milli")
var endTimeMilli: Long = startTimeMilli,
@ColumnInfo(name = "quality_rating")
var sleepQuality: Int = -1
)
- 建構並執行程式碼,確保其沒有錯誤。
在這項工作中,您會定義資料存取物件 (DAO)。在 Android 上,DAO 提供插入、刪除及更新資料庫的便利方法。
使用 Room
資料庫時,您可以在程式碼中定義並呼叫 Kotlin 函式,藉此查詢資料庫。這些 Kotlin 函式會對應至 SQL 查詢。您可以在 DAO 中使用註解來定義這些對應,Room
則會建立必要的程式碼。
您可以將 DAO 定義為定義資料庫存取介面的自訂介面。
針對常見的資料庫作業,Room
程式庫可提供便利的註解,例如 @Insert
、@Delete
和 @Update
。除此之外,您還可以使用 @Query
註解。您可以編寫受 SQLite 支援的任何查詢。
當您在 Android Studio 中建立查詢時,編譯器也會檢查 SQL 查詢是否有語法錯誤。
針對睡眠夜晚的睡眠追蹤器資料庫,您必須能夠執行以下操作:
- 插入新的夜晚。
- 更新現有夜晚,以更新結束時間和品質分數。
- 根據金鑰,取得特定夜晚的睡眠時間。
- 查詢整晚,以便顯示。
- 取得最近的一晚
- 刪除資料庫中的所有項目。
步驟 1:建立 SleepDatabase DAO
- 在
database
套件中開啟SleepDatabaseDao.kt
。 - 請注意,
interface
SleepDatabaseDao
會以@Dao
加上註解。所有 DAO 都必須透過@Dao
關鍵字加上註解。
@Dao
interface SleepDatabaseDao {}
- 在介面內文中,新增
@Insert
註解。在@Insert
下方加入insert()
函式,將Entity
類別SleepNight
的執行個體做為引數。
這樣就大功告成了!Room
會產生所有必要的程式碼,以便將SleepNight
插入資料庫。從 Kotlin 程式碼呼叫insert()
時,Room
會執行 SQL 查詢,將實體插入資料庫。(注意:您可以視需求呼叫 函式)。
@Insert
fun insert(night: SleepNight)
- 為一個
SleepNight
新增帶有update()
函式的@Update
註解。更新的實體是擁有與傳送金鑰相同的金鑰的實體。您可以更新實體的部分或所有屬性。
@Update
fun update(night: SleepNight)
其餘功能不會提供便利註解,因此您必須使用 @Query
註解並提供 SQLite 查詢。
- 新增具有
get()
函式的@Query
註解,該函式會接受Long
key
引數並傳回空值SleepNight
。您就會看到遺漏參數的錯誤。
@Query
fun get(key: Long): SleepNight?
- 查詢會以字串參數的形式提供給註解。在
@Query
中加入參數。將String
設為 SQLite 查詢。
- 從
daily_sleep_quality_table
中選取所有資料欄 WHERE
nightId
與 :key
引數相符。
請注意:key
。您可以在查詢中使用冒號標記法來參照函式中的引數。
("SELECT * from daily_sleep_quality_table WHERE nightId = :key")
- 再新增一個含有
clear()
函式的@Query
和 SQLite 查詢,從daily_sleep_quality_table
的DELETE
具備所有功能。這項查詢不會一併刪除資料表本身。@Delete
註解會刪除 1 個項目,您可以使用@Delete
並提供要刪除的清單。缺點是您需要擷取或瞭解表格中的內容。@Delete
註解很適合用來刪除特定項目,但無法有效地清除資料表中的所有項目。
@Query("DELETE FROM daily_sleep_quality_table")
fun clear()
- 新增具有
getTonight()
函式的@Query
。將getTonight()
傳回的SleepNight
設為空值,這樣函式就能處理資料表空白的情況。(表格的開頭和空白處均無內容。)
如要取得「今晚」的資料庫資料,請撰寫 SQLite 查詢,以遞減順序傳回nightId
排序結果清單的第一個元素。使用LIMIT 1
只傳回一個元素。
@Query("SELECT * FROM daily_sleep_quality_table ORDER BY nightId DESC LIMIT 1")
fun getTonight(): SleepNight?
- 新增具有
getAllNights()
函式的@Query
:
- 讓 SQLite 查詢從
daily_sleep_quality_table
傳回所有資料欄,並依遞減順序排列。 - 讓
getAllNights()
將SleepNight
實體清單做為LiveData
傳回。Room
將隨時為您更新這個LiveData
,因此您只需要明確取得資料一次即可。 - 您可能需要從
androidx.lifecycle.LiveData
匯入LiveData
。
@Query("SELECT * FROM daily_sleep_quality_table ORDER BY nightId DESC")
fun getAllNights(): LiveData<List<SleepNight>>
- 雖然您看不到任何變更,但請進行檢查,確保應用程式沒有任何錯誤。
在這項工作中,您會建立 Room
資料庫,使用您在先前工作中建立的 Entity
和 DAO。
您必須建立抽象資料庫訴訟保留類別,並加上 @Database
的註解。此類別有一個方法,可以在資料庫不存在時建立資料庫執行個體,或者傳回現有資料庫的參照。
取得 Room
資料庫需要一點點時間,因此在開始使用程式碼之前,請先完成下列一般程序:
- 建立
extends RoomDatabase
的public abstract
類別。此類別為資料庫持有者。此類別為抽象化,因為Room
會為您建立實作。 - 使用
@Database
為類別加上註解。在引數中宣告資料庫的實體,並設定版本號碼。 - 在
companion
物件中,定義傳回SleepDatabaseDao
的抽象方法或屬性。Room
將為您產生內文。 - 整個應用程式只需要一個
Room
資料庫例項,因此請將RoomDatabase
設為單例。 - 只有在資料庫不存在時,才使用
Room
的資料庫建構工具來建立資料庫。如果沒有,則傳回現有資料庫。
步驟 1:建立資料庫
- 在
database
套件中開啟SleepDatabase.kt
。 - 在這個檔案中,建立名為「
SleepDatabase
」的abstract
類別,藉此擴充「RoomDatabase
」。
使用@Database
為課程加上註解。
@Database()
abstract class SleepDatabase : RoomDatabase() {}
- 您會看到缺少實體和版本參數的錯誤訊息。
@Database
註解需要幾個引數,Room
才能建構資料庫。
- 將
SleepNight
當做唯一包含entities
清單的項目。 - 將
version
設為1
。 只要您更改架構,就必須增加版本號碼。 - 只要將
exportSchema
設為false
,即可不保留結構定義版本記錄的備份。
entities = [SleepNight::class], version = 1, exportSchema = false
- 資料庫需要知道該 DAO。在類別的主體中宣告可傳回
SleepDatabaseDao
的抽象值。您可以有多個 DAO。
abstract val sleepDatabaseDao: SleepDatabaseDao
- 在下方定義
companion
物件。隨附物件可讓用戶端存取建立或取得資料庫的方法,而不必將類別執行個體化。此類別的唯一目的就是提供資料庫,因此不會有理由將資料庫執行個體化。
companion object {}
- 在
companion
物件中,宣告資料庫的私人空值變數INSTANCE
,並將其初始化為null
。建立變數後,INSTANCE
變數會保留對資料庫的參照。如此一來,您就不必重複建立連線至資料庫的昂貴費用。
使用 @Volatile
為 INSTANCE
加上註解。系統不會快取揮發變數的值,而所有寫入和讀取作業都將在主記憶體內完成。這麼做可確保 INSTANCE
的值一律為最新狀態,且與所有執行執行緒相同。換句話說,只要一個執行緒對 INSTANCE
所做的變更,就能立即顯示在所有其他會話串上;在這種情況下,如果兩個執行緒分別在快取中更新同一個實體,就會造成問題。
@Volatile
private var INSTANCE: SleepDatabase? = null
- 在
INSTANCE
下方,請持續在companion
物件中,使用資料庫建構所需的Context
參數定義getInstance()
方法。傳回類型SleepDatabase
。由於getInstance()
尚未傳回任何內容,因此系統會顯示錯誤訊息。
fun getInstance(context: Context): SleepDatabase {}
- 在「
getInstance()
」內新增「synchronized{}
」區塊。輸入this
以存取背景資訊。
多個執行緒可能會同時要求資料庫執行個體,因此會產生兩個資料庫,而不是一個資料庫。這個範例應用程式可能比較不會發生這個問題,但較複雜的應用程式可能發生問題。將程式碼包裝成synchronized
代表資料庫一次執行了一項程式碼區塊,可確保資料庫僅初始化一次。
synchronized(this) {}
- 在同步處理的區塊內,將
INSTANCE
的值複製到本機變數instance
。因此,建議您善用智慧投放功能,這項功能只適合本機變數使用。
var instance = INSTANCE
- 在
synchronized
區塊中,return instance
在synchronized
區塊的結尾。請忽略傳回類型不符的錯誤;完成之後,您就永遠不會傳回 null。
return instance
- 在
return
陳述式上方,加入if
陳述式來檢查instance
是否為空值,也就是還沒有資料庫。
if (instance == null) {}
- 如果
instance
是null
,請使用資料庫建構工具取得資料庫。在if
陳述式的主體中叫用Room.databaseBuilder
,並提供您傳送的內容、資料庫類別和資料庫名稱 (sleep_history_database
)。如要移除錯誤,只要按照下列步驟加入遷移策略和build()
即可。
instance = Room.databaseBuilder(
context.applicationContext,
SleepDatabase::class.java,
"sleep_history_database")
- 將必要的遷移策略新增至建構工具。使用
.fallbackToDestructiveMigration()
。
一般來說,當架構變更時,您必須提供遷移策略,並提供遷移策略。遷移物件是一個物件,用於定義您要擷取舊架構的所有資料列,並將這些物件轉換為新結構定義中的資料列,以免遺失資料。遷移不在這個程式碼研究室的範圍內。其中一個簡單的解決方法是刪除並重新建構資料庫,但代表資料會遺失。
.fallbackToDestructiveMigration()
- 最後,呼叫
.build()
。
.build()
- 將
INSTANCE = instance
指定為if
陳述式中的最後一個步驟。
INSTANCE = instance
- 您的最終程式碼看起來應該像這樣:
@Database(entities = [SleepNight::class], version = 1, exportSchema = false)
abstract class SleepDatabase : RoomDatabase() {
abstract val sleepDatabaseDao: SleepDatabaseDao
companion object {
@Volatile
private var INSTANCE: SleepDatabase? = null
fun getInstance(context: Context): SleepDatabase {
synchronized(this) {
var instance = INSTANCE
if (instance == null) {
instance = Room.databaseBuilder(
context.applicationContext,
SleepDatabase::class.java,
"sleep_history_database"
)
.fallbackToDestructiveMigration()
.build()
INSTANCE = instance
}
return instance
}
}
}
}
- 建構並執行程式碼。
您現在可以使用 Room
資料庫的所有建構模塊。這個程式碼可以編譯並執行,但無法判斷它是否正常運作。因此,現在您可以加入一些基本測試。
步驟 2:測試 SleepDatabase
在這個步驟中,您將執行提供的測試來確認資料庫是否正常運作。這有助於您在建立資料庫之前,確保資料庫運作正常。提供的測試具有基本功能。針對正式版應用程式,您可以執行所有 DAO 中的所有函式和查詢。
入門應用程式含有 androidTest 資料夾。這個 androidTest 資料夾包含執行 Android 檢測的單元測試,這是說測試需要 Android 架構,因此您需要在實體或虛擬裝置上執行測試。當然,您也可以建立及執行不含 Android 架構的純單元測試。
- 在 Android Studio 中開啟 androidTest 資料夾,然後開啟 SleepDatabaseTest 檔案。
- 如要取消註解程式碼,請選取所有已加註的程式碼,然後按下
Cmd+/
或Control+/
鍵盤快速鍵。 - 請看一下檔案。
這是測試代碼的快速執行方法,因為這是另一段可以重複使用的程式碼:
SleepDabaseTest
屬於測試類別。@RunWith
註解可用來識別測試執行器,這是用來設定及執行測試的程式。- 在設定過程中,系統會執行標註
@Before
的函式,並以SleepDatabaseDao
建立記憶體內SleepDatabase
。「記憶體內」表示這個資料庫並未儲存在檔案系統上,因此會在測試執行完成後刪除。 - 此外,建立記憶體內資料庫時,程式碼會呼叫另一個測試專屬方法
allowMainThreadQueries
。根據預設,如果您嘗試在主執行緒上執行查詢,就會收到錯誤訊息。此方法可讓您對主執行緒執行測試,但只能在對測試時執行。 - 在以
@Test
註解的測試方法中,您可以建立、插入及擷取SleepNight
,並聲明兩者相同。如有任何問題,請提出例外狀況。在實際測試中,您會使用多種@Test
方法。 - 測試完成後,系統會執行標註
@After
的函式,藉此關閉資料庫。
- 在專案窗格中,對測試檔案按一下滑鼠右鍵,並選取 Run 'SleepDatabaseTest'。
- 執行測試後,請在「SleepDatabaseTest」窗格中確認所有測試均通過。
由於通過所有測試,你現在已經知道了以下幾點:
- 資料庫建立正確。
- 您可以將
SleepNight
插入資料庫。 - 但你可以取回
SleepNight
。 - 「
SleepNight
」的值品質正確。
Android Studio 專案:TrackMySleepqualityRoomAndTesting
測試資料庫時,您必須執行 DAO 中定義的所有方法。要完成測試,請新增並執行測試以執行其他 DAO 方法。
- 將資料表定義為具有
@Entity
註解的資料類別。定義具有@ColumnInfo
註解的屬性做為資料表中的資料欄。 - 定義資料存取物件 (DAO) 做為標有
@Dao
註解的介面。DAO 會將 Kotlin 函式對應至資料庫查詢。 - 使用註解來定義
@Insert
、@Delete
和@Update
函式。 - 使用
@Query
註解搭配 SQLite 查詢字串做為任何其他查詢的參數。 - 建立具有可傳回資料庫的
getInstance()
函式的抽象類別。 - 使用檢測設備測試資料庫和 DAO 是否正常運作。您可將提供的測試當做範本使用。
Udacity 課程:
Android 開發人員說明文件:
RoomDatabase
Database
(註解)- 您可以搭配
Room
使用原始查詢 Roomdatabase.Builder
- 測試訓練
SQLiteDatabase
類別Dao
Room
個持續性程式庫
其他文件和文章:
- 單例模式
- 來自 Google 開發人員專家的討論:正確使用揮發性和同步處理
- 夥伴物件
- 瞭解會議室中的遷移作業
- 測試會議室遷移作業
- 資料庫記錄
- SQLite 網站
- 由 SQLite 解讀的 SQL 完整說明
這個部分會列出在代碼研究室中,受老師主導的課程作業的可能學生作業。由老師自行決定要執行下列動作:
- 視需要指派家庭作業。
- 告知學生如何提交家庭作業。
- 批改家庭作業。
老師可視需要使用這些建議,並視情況指派其他合適的家庭作業。
如果您是自行操作本程式碼研究室,歡迎透過這些家庭作業來測試自己的知識。
回答這些問題
第 1 題
如何指明某個類別代表要儲存在 Room
資料庫中的實體?
- 將類別擴充
DatabaseEntity
。 - 使用
@Entity
為類別加上註解。 - 使用
@Database
為類別加上註解。 - 讓類別擴充
RoomEntity
,並使用@Room
為類別加上註解。
第 2 題
DAO (資料存取物件) 是 Room
提供的介面,用來將 Kotlin 函式對應至資料庫查詢。
如何指明介面代表 Room
資料庫的 DAO?
- 讓介面擴充
RoomDAO
。 - 讓介面延伸
EntityDao
,然後實作DaoConnection()
方法。 - 使用
@Dao
為介面加上註解。 - 使用
@RoomConnection
為介面加上註解。
第 3 題
關於 Room
資料庫,下列敘述何者正確?請選擇所有適用選項。
- 您可以將
Room
資料庫的資料表定義為已加註的資料類別。 - 如果從查詢傳回
LiveData
,如果Room
有所異動,Room
會為您更新LiveData
。 - 每個
Room
資料庫都必須有一個 DAO,並且只能有一個。 - 要將類別識別為
Room
資料庫,請將其設為RoomDatabase
的子類別,並以@Database
加上註解。
第 4 題
你可以在 @Dao
介面中使用下列哪些註解?請選擇所有適用選項。
@Get
@Update
@Insert
@Query
第 5 題
如何確認資料庫是否正常運作?請選取所有適用選項。
- 撰寫檢測測試。
- 繼續寫入並執行應用程式,直到應用程式顯示資料為止。
- 將呼叫替換為 DAO 介面中的方法,以呼叫
Entity
類別中對等方法的呼叫。 - 執行
Room
程式庫提供的verifyDatabase()
函式。
開始下一門課程:
如要瞭解本課程中其他程式碼研究室的連結,請參閱 Android Kotlin 基礎程式碼程式碼到達網頁。