使用 Android Jetpack 的 Room 部分将数据保存到本地数据库。
处理大量结构化数据的应用可极大地受益于在本地保留这些数据。最常见的使用场景是缓存相关的数据,这样一来,当设备无法访问网络时,用户仍然可以在离线状态下浏览该内容。
Room 持久性库在 SQLite 上提供了一个抽象层,以便在充分利用 SQLite 的强大功能的同时,能够流畅地访问数据库。具体来说,Room 具有以下优势:
- 提供针对 SQL 查询的编译时验证。
- 提供方便注解,可最大限度减少重复和容易出错的样板代码。
- 简化了数据库迁移路径。
出于这些方面的考虑,我们强烈建议您使用 Room,而不是直接使用 SQLite API。
设置
如需在应用中使用 Room,请将以下依赖项添加到应用的 build.gradle
文件。
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") }
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
表中的一行。
@Entity data class User( @PrimaryKey val uid: Int, @ColumnInfo(name = "first_name") val firstName: String?, @ColumnInfo(name = "last_name") val lastName: String? )
@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
表中的数据交互的方法。
@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) }
@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 类的实例。
@Database(entities = [User::class], version = 1) abstract class AppDatabase : RoomDatabase() { abstract fun userDao(): UserDao }
@Database(entities = {User.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { public abstract UserDao userDao(); }
注意:如果您的应用在单个进程中运行,在实例化 AppDatabase
对象时应遵循单例设计模式。每个 RoomDatabase
实例的成本相当高,而您几乎不需要在单个进程中访问多个实例。
如果您的应用在多个进程中运行,请在数据库构建器调用中包含 enableMultiInstanceInvalidation()
。这样,如果您在每个进程中都有一个 AppDatabase
实例,可以在一个进程中使共享数据库文件失效,并且这种失效会自动传播到其他进程中 AppDatabase
的实例。
用法
定义数据实体、DAO 和数据库对象后,您可以使用以下代码创建数据库实例:
val db = Room.databaseBuilder( applicationContext, AppDatabase::class.java, "database-name" ).build()
AppDatabase db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "database-name").build();
然后,您可以使用 AppDatabase
中的抽象方法获取 DAO 的实例,转而可以使用 DAO 实例中的方法与数据库进行交互:
val userDao = db.userDao() val users: List<User> = userDao.getAll()
UserDao userDao = db.userDao(); List<User> users = userDao.getAll();
其他资源
如需详细了解 Room,请参阅下面列出的其他资源:
示例
In order to launch new features on their Android app, Headspace spent 8 months refactoring their architecture and rewriting in Kotlin. Learn how this reboot helped their business grow. SmartNews helps millions of people discover their world everyday by sharing timely news from a diverse set of news sources. Twitter is one of the most widely used social media platforms where users can see what’s happening in the world at any given moment. The Google Home app helps set up, manage, and control your Google Home, Google Nest, and Chromecast devices—plus thousands of connected home products like lights, cameras, thermostats, and more. Duolingo is one of the most popular language learning platforms in the world, and one of the most-downloaded free education apps on Google Play, with more than 200 million downloads.Headspace's Android reboot increases monthly active users by 15%
SmartNews reduces lines of code by 20% and improves team morale with Kotlin
Twitter increases developer productivity and code reliability with Kotlin
Google Home reduces #1 cause of crashes by 33%
Duolingo completes migration to Kotlin and reduces its line count by an average of 30%