Jatpack Room 数据库封装:简洁、通用、高性能的持久化解决方案
本文提供了一种对 Android Jetpack Room 数据库的终极封装方案,通过通用工具类和简洁的 API,显著简化数据库操作代码,提升开发效率。封装支持协程和 Flow,确保线程安全和高性能,同时具备极强的扩展性,适用于各种复杂场景。无论是初学者还是资深开发者,都能快速上手并应用于实际项目中。
完整代码实现
1. 添加依赖
在 build.gradle 中添加 Room 和 Kotlin 协程依
赖:
dependencies {
def room_version = "2.6.1" // 使用最新版本
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version" // 支持协程
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3" // 协程支持
}
2. 定义通用 BaseDao
封装常见的增删改查操作:
import androidx.room.*
import kotlinx.coroutines.flow.Flow
interface BaseDao<T> {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(entity: T)
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertAll(entities: List<T>)
@Update
suspend fun update(entity: T)
@Delete
suspend fun delete(entity: T)
@Query("DELETE FROM :tableName")
suspend fun deleteAll(tableName: String)
}
3. 定义 DatabaseHelper
封装数据库初始化和 DAO 获取逻辑:
import android.content.Context
import androidx.room.Room
import androidx.room.RoomDatabase
abstract class DatabaseHelper<DB : RoomDatabase>(
private val context: Context,
private val dbClass: Class<DB>,
private val dbName: String
) {
@Volatile
private var instance: DB? = null
fun getDatabase(): DB {
return instance ?: synchronized(this) {
val newInstance = Room.databaseBuilder(
context.applicationContext,
dbClass,
dbName
).build()
instance = newInstance
newInstance
}
}
inline fun <reified T : BaseDao<E>, E> getDao(): T {
return getDatabase().getDao(T::class.java)
}
}
4. 定义实体类和 DAO
以 User 表为例:
实体类
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "user")
data class User(
@PrimaryKey val id: Int,
val name: String,
val age: Int
)
DAO 接口
import androidx.room.Dao
import androidx.room.Query
import kotlinx.coroutines.flow.Flow
@Dao
interface UserDao : BaseDao<User> {
@Query("SELECT * FROM user")
fun getAllUsers(): Flow<List<User>>
@Query("SELECT * FROM user WHERE id = :userId")
suspend fun getUserById(userId: Int): User?
}
5. 定义 AppDatabase
创建 Room 数据库实例:
import androidx.room.Database
import androidx.room.RoomDatabase
@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}
6. 使用封装工具类
在应用中使用封装后的工具类进行数据库操作。
定义 Repository
class UserRepository(context: Context) {
private val databaseHelper = DatabaseHelper(context, AppDatabase::class.java, "app_database")
private val userDao: UserDao by lazy { databaseHelper.getDao() }
val allUsers: Flow<List<User>> = userDao.getAllUsers()
suspend fun insert(user: User) {
userDao.insert(user)
}
suspend fun update(user: User) {
userDao.update(user)
}
suspend fun delete(user: User) {
userDao.delete(user)
}
suspend fun getUserById(userId: Int): User? {
return userDao.getUserById(userId)
}
}
在 ViewModel 中使用
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch
class UserViewModel(context: Context) : ViewModel() {
private val repository = UserRepository(context)
val allUsers = repository.allUsers
fun insert(user: User) = viewModelScope.launch {
repository.insert(user)
}
fun update(user: User) = viewModelScope.launch {
repository.update(user)
}
fun delete(user: User) = viewModelScope.launch {
repository.delete(user)
}
fun getUserById(userId: Int) = viewModelScope.launch {
val user = repository.getUserById(userId)
// 处理查询结果
}
}
7. 进一步优化
7.1 支持依赖注入(Hilt)
在 AppModule 中提供数据库和 DAO 的依赖:
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Provides
@Singleton
fun provideAppDatabase(@ApplicationContext context: Context): AppDatabase {
return Room.databaseBuilder(
context,
AppDatabase::class.java,
"app_database"
).build()
}
@Provides
fun provideUserDao(database: AppDatabase): UserDao {
return database.userDao()
}
}
在 Repository 中注入 DAO:
class UserRepository @Inject constructor(private val userDao: UserDao) {
// ...
}
7.2 支持测试
在单元测试中使用内存数据库:
import androidx.room.testing.MigrationTestHelper
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Rule
import org.junit.Test
class UserDaoTest {
@get:Rule
val helper = MigrationTestHelper(
InstrumentationRegistry.getInstrumentation(),
AppDatabase::class.java
)
@Test
fun testInsertAndQuery() {
val database = helper.createDatabase("test_db", 1).apply {
// 插入测试数据
execSQL("INSERT INTO user (id, name, age) VALUES (1, 'John', 25)")
close()
}
// 查询并验证数据
val user = database.query("SELECT * FROM user WHERE id = 1", null)
assert(user.moveToFirst())
assertEquals("John", user.getString(user.getColumnIndex("name")))
}
}
8. 总结
通过以上封装,Room 数据库的使用变得更加简洁、通用和高性能。关键点包括:
通用 BaseDao 封装常见操作。
DatabaseHelper 简化数据库初始化和 DAO 获取。
支持协程和 Flow,确保线程安全。
结合依赖注入和测试支持,提升代码质量和可维护性。
这套封装方案适用于大多数 Android 项目,能够显著提升开发效率和代码质量。