使用 Room (Android Jetpack 的一部分) 將資料儲存在本機資料庫。
如果應用程式可以處理大量結構化資料,將可以在本機保存資料。最常見的用途是快取相關資料片段,這樣即使裝置無法存取網路,使用者仍可在離線時瀏覽這類內容。
Room 持續性資料庫透過 SQLite 提供抽象層,可讓資料庫順暢存取,同時充分發揮 SQLite 的效用。特別是,Room 具有下列優點:
- 提供 SQL 查詢的編譯時間驗證。
- 盡可能減少重複且容易出錯的樣板程式碼的便利註解。
- 簡化資料庫遷移路徑。
基於以上考量,我們強烈建議您使用 Room,而非直接使用 SQLite API。
設定
如要在應用程式中使用 Room,請在應用程式的 build.gradle
檔案中新增下列依附元件。
Kotlin
dependencies { val room_version = "2.6.1" implementation("androidx.room:room-runtime:$room_version") // If this project uses any Kotlin source, use Kotlin Symbol Processing (KSP) // See Add the KSP plugin to your project ksp("androidx.room:room-compiler:$room_version") // If this project only uses Java source, use the Java annotationProcessor // No additional plugins are necessary annotationProcessor("androidx.room:room-compiler:$room_version") // optional - Kotlin Extensions and Coroutines support for Room implementation("androidx.room:room-ktx:$room_version") // optional - RxJava2 support for Room implementation("androidx.room:room-rxjava2:$room_version") // optional - RxJava3 support for Room implementation("androidx.room:room-rxjava3:$room_version") // optional - Guava support for Room, including Optional and ListenableFuture implementation("androidx.room:room-guava:$room_version") // optional - Test helpers testImplementation("androidx.room:room-testing:$room_version") // optional - Paging 3 Integration implementation("androidx.room:room-paging:$room_version") }
Groovy
dependencies { def room_version = "2.6.1" implementation "androidx.room:room-runtime:$room_version" // If this project uses any Kotlin source, use Kotlin Symbol Processing (KSP) // See KSP Quickstart to add KSP to your build ksp "androidx.room:room-compiler:$room_version" // If this project only uses Java source, use the Java annotationProcessor // No additional plugins are necessary annotationProcessor "androidx.room:room-compiler:$room_version" // optional - RxJava2 support for Room implementation "androidx.room:room-rxjava2:$room_version" // optional - RxJava3 support for Room implementation "androidx.room:room-rxjava3:$room_version" // optional - Guava support for Room, including Optional and ListenableFuture implementation "androidx.room:room-guava:$room_version" // optional - Test helpers testImplementation "androidx.room:room-testing:$room_version" // optional - Paging 3 Integration implementation "androidx.room:room-paging:$room_version" }
主要元件
Room 有三個主要元件:
- 資料庫類別,用於保存資料庫並做為應用程式保留資料基礎連線的主要存取點。
- 資料實體,代表應用程式資料庫中的資料表。
- 資料存取物件 (DAO),提供應用程式可用於查詢、更新、插入及刪除資料庫中資料的方法。
資料庫類別可為您的應用程式提供與該資料庫關聯的 DAO 例項。反過來,應用程式可以使用 DAO 擷取資料庫中的資料,做為關聯資料實體物件的例項。應用程式也可以使用定義的資料實體,更新對應資料表中的資料列,或是建立新的資料列來插入資料。圖 1 說明 Room 不同元件之間的關係。
實作範例
本節說明採用單一資料實體和單一 DAO 的 Room 資料庫實作範例。
資料實體
以下程式碼定義 User
資料實體。每個 User
例項都代表應用程式資料庫中 user
資料表的一個資料列。
Kotlin
@Entity data class User( @PrimaryKey val uid: Int, @ColumnInfo(name = "first_name") val firstName: String?, @ColumnInfo(name = "last_name") val lastName: String? )
Java
@Entity public class User { @PrimaryKey public int uid; @ColumnInfo(name = "first_name") public String firstName; @ColumnInfo(name = "last_name") public String lastName; }
如要進一步瞭解 Room 中的資料實體,請參閱「使用 Room 實體定義資料」。
資料存取物件 (DAO)
以下程式碼定義了名稱為 UserDao
的 DAO。UserDao
提供了可讓其餘應用程式與 user
資料表中資料互動所用的方法。
Kotlin
@Dao interface UserDao { @Query("SELECT * FROM user") fun getAll(): List<User> @Query("SELECT * FROM user WHERE uid IN (:userIds)") fun loadAllByIds(userIds: IntArray): List<User> @Query("SELECT * FROM user WHERE first_name LIKE :first AND " + "last_name LIKE :last LIMIT 1") fun findByName(first: String, last: String): User @Insert fun insertAll(vararg users: User) @Delete fun delete(user: User) }
Java
@Dao public interface UserDao { @Query("SELECT * FROM user") List<User> getAll(); @Query("SELECT * FROM user WHERE uid IN (:userIds)") List<User> loadAllByIds(int[] userIds); @Query("SELECT * FROM user WHERE first_name LIKE :first AND " + "last_name LIKE :last LIMIT 1") User findByName(String first, String last); @Insert void insertAll(User... users); @Delete void delete(User user); }
如要進一步瞭解 DAO,請參閱「使用 Room DAO 存取資料」。
資料庫
以下程式碼定義了用於保存資料庫的 AppDatabase
類別。AppDatabase
定義了資料庫設定,並做為應用程式保留資料的主要存取點。資料庫類別必須符合下列條件:
- 必須使用
@Database
註解來備註類別,其中包含entities
陣列,列出了與資料庫關聯的所有資料實體。 - 類別必須是擴充
RoomDatabase
的抽象類別。 - 針對與資料庫關聯的每個 DAO 類別,資料庫類別必須定義沒有引數的抽象方法,並傳回 DAO 類別的例項。
Kotlin
@Database(entities = [User::class], version = 1) abstract class AppDatabase : RoomDatabase() { abstract fun userDao(): UserDao }
Java
@Database(entities = {User.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { public abstract UserDao userDao(); }
注意: 如果您的應用程式以單一程序執行,則在對 AppDatabase
物件執行個體化時,請遵循單例設計模式。每個 RoomDatabase
執行個體都非常昂貴,但在單一程序中,您通常很少需要存取多個執行個體。
如果您的應用程式在多個程序中執行,請將 enableMultiInstanceInvalidation()
納入資料庫建構工具叫用。如此一來,您在每個程序都有一個 AppDatabase
執行個體時,便可在某個程序中作廢共用資料庫檔案,而此無效變更也會自動套用至其他程序內的 AppDatabase
執行個體。
用量
定義資料實體、DAO 和資料庫物件後,您可以使用以下程式碼建立資料庫例項:
Kotlin
val db = Room.databaseBuilder( applicationContext, AppDatabase::class.java, "database-name" ).build()
Java
AppDatabase db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "database-name").build();
接著,您可以使用 AppDatabase
的抽象方法來取得 DAO 例項。反過來,您可以使用 DAO 例項的方法與資料庫互動:
Kotlin
val userDao = db.userDao() val users: List<User> = userDao.getAll()
Java
UserDao userDao = db.userDao(); List<User> users = userDao.getAll();
其他資源
如要進一步瞭解 Room,請參閱下列其他資源: