当前位置: 首页 > news >正文

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 项目,能够显著提升开发效率和代码质量。

相关文章:

  • 开启AI开发新时代——全解析Dify开源LLM应用开发平台
  • maven wrapper的使用
  • 【Godot4.4】写入和读取ZIP文件
  • 《灵珠觉醒:从零到算法金仙的C++修炼》卷三·天劫试炼(34)混元金斗装万物 - 0-1背包问题(二维DP)
  • React.js 基础与进阶教程
  • 【网络安全 | 漏洞挖掘】四链路账户接管
  • 视频理解之Actionclip(论文宏观解读)
  • SQL日期处理
  • Java的JDBC编程
  • BFS最短路径(十七)675. 为高尔夫比赛砍树 困难
  • 图像识别技术与应用(十六)
  • 科技工作者之家建设扬帆起航,为科技人才提供更多优质服务
  • lua C语言api学习1 编译第一个程序
  • 【巨人网络】25届春招、26届实习内推码,面经
  • nginx反向代理应用
  • SMC自修改
  • 二进制安装指定版本的MariaDBv10.11.6
  • 珠算之珠心算观想算盘
  • 基于Python+Vue开发的鲜花商城管理系统源码+运行步骤
  • 深度学习基础:线性代数本质4——矩阵乘法
  • 海外考古大家访谈|冈村秀典:礼制的形成与早期中国
  • 六省会共建交通枢纽集群,中部离经济“第五极”有多远?
  • 悬疑剧背后的女编剧:创作的差异不在性别,而在经验
  • 乌总统:若与普京会谈,全面停火和交换战俘是主要议题
  • 【社论】个人破产探索,要守住“诚实而不幸”的底线
  • “应急侠”上线,应急管理部正式发布应急科普IP形象