Android Jetpack组件Room使用

使用 Android Jetpack 的 Room 部分 将数据保存到本地数据库。

https://developer.android.google.cn/training/data-storage/room?hl=zh-cn#kts

请将以下依赖项添加到应用的 build.gradle 文件

    dependencies {
    val room_version = "2.5.0"

    //核心库
    implementation("androidx.room:room-runtime:$room_version")
    
    //To use Kotlin Symbol Processing (annotationProcessor/kapt/KSP)(本项目使用kapt)
    kapt("androidx.room:room-compiler:$room_version")

    // optional - Kotlin Extensions and Coroutines support for Room
    implementation("androidx.room:room-ktx:$room_version")

    // optional - RxJava2/RxJava3/Guava support for Room(本项目使用RxJava3)
    implementation("androidx.room:room-rxjava3:$room_version")

    // optional - Test helpers
    testImplementation("androidx.room:room-testing:$room_version")

    // optional - Paging 3 Integration(查询分页数据)
    implementation("androidx.room:room-paging:$room_version")
    } 

实现示例

数据实体

@Entity
public class User {
@PrimaryKey
public int uid;

    @ColumnInfo(name = "first_name")
    public String firstName;

    @ColumnInfo(name = "last_name")
    public String lastName;
}

数据访问对象 (DAO)

@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)
}

数据库

//该类必须带有 @Database 注解,该注解包含列出所有与数据库关联的数据实体的 entities 数组。
//该类必须是一个抽象类,用于扩展 RoomDatabase。
//对于与数据库关联的每个 DAO 类,数据库类必须定义一个具有零参数的抽象方法,并返回 DAO 类的实例。

@Database(
entities = [UserBean::class],
version = 2,
//    exportSchema = false 
)
abstract class TestDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}

用法(RoomApp)

/**
 * Room数据库初始化
 */
roomDB = AppDatabase.getInstance(this)!!

AppDataBase类

@Database(
entities = [UserBean::class],
version = 1,
exportSchema = false
)
abstract class AppDatabase() : RoomDatabase() {
companion object {
private var appDatabase: AppDatabase? = null

        //单例模式
        @Synchronized
        open fun getInstance(context: Context): AppDatabase? {
            if (appDatabase == null) {
                appDatabase = Room.databaseBuilder(context.applicationContext, AppDatabase::class.java, "test_app_db")
                    .allowMainThreadQueries() //强制要求在主线程运行(真实环境中不使用)
                    .addCallback(DataBaseCreateCallBack)//数据库创建回调调用
                    .build()
            }
            return appDatabase
        }
        private object DataBaseCreateCallBack : Callback() {
            //第一次创建数据库时调用
            override fun onCreate(db: SupportSQLiteDatabase) {
                super.onCreate(db)
                LogUtils.e("first onCreate db version: " + db.version)
            }
        }
    }

    abstract fun userDao(): UserDao
}   

然后,您可以使用 TestDatabase 中的抽象方法获取 DAO 的实例,转而可以使用 DAO 实例中的方法与数据库进行交互:

val userDao = db.userDao()
val users: List<User> = userDao.getAll()

错误提示:Schema export directory is not provided to the annotation processor so we cannot export the schema.You can either provide room.schemaLocation annotation processor argument OR set exportSchema to false.

解决方式一:给RoomDatabase设置exportSchema注解为false

@Database(
entities = [UserBean::class],
version = 2,
//    exportSchema = false 
)
abstract class TestDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}

解决方式二:给RoomDatabase设置exportSchema注解为false

在项目中gradle中通过 kapt 注解,为room.schemaLocation指定schemas的子文件夹。
android {
.....
defaultConfig {
    .....
    if (isModule.toBoolean()) {
        // 独立调试时添加 applicationId ,集成调试时移除
        applicationId "com.app.sql"
    }
}
kapt {
    arguments {
        arg("room.schemaLocation", "$projectDir/schemas")
    }
}
sourceSets {
    main {
        // 独立调试与集成调试时使用不同的 AndroidManifest.xml 文件
        if (isModule.toBoolean()) {
            manifest.srcFile 'src/main/moduleManifest/AndroidManifest.xml'
        } else {
            manifest.srcFile 'src/main/AndroidManifest.xml'
        }
    }
}
.....
}

版本更新/表增加字段(AppDataBase类修改)

@Database(
entities = [UserBean::class],
version = 2,
exportSchema = false
)
abstract class AppDatabase() : RoomDatabase() {
companion object {
private var appDatabase: AppDatabase? = null

        //单例模式
        @Synchronized
        open fun getInstance(context: Context): AppDatabase? {
            if (appDatabase == null) {
                appDatabase = Room.databaseBuilder(context.applicationContext, AppDatabase::class.java, "test_app_db")
                    .allowMainThreadQueries() //强制要求在主线程运行(真实环境中不使用)
                    //.fallbackToDestructiveMigration()//破坏试的迁移.原有的数据被清空,重新建立新表
                    .addMigrations(MIGRATION_1_2)
                    .addCallback(DataBaseCreateCallBack)//数据库创建回调调用
                    .build()
            }
            return appDatabase
        }

        //版本号  1到2(1是手机上的版本,2是需要升级使用的版本)
        val MIGRATION_1_2: Migration = object : Migration(1, 2) {
            override fun migrate(@NonNull database: SupportSQLiteDatabase) {
                //没有布尔值,用INTEGER代替
                //使用"ALTER TABLE Word  ADD COLUMN bar_data2 INTEGER  NOT NULL DEFAULT 1"出错。
                //使用下面分开的形式,可以正确执行(INTEGER 字段 需要加上 NOT NULL DEFAULT 0)
                database.execSQL("ALTER TABLE user " + " ADD COLUMN uid TEXT")
                //注意:执行的sql语言,“NOT NULL DEFAULT 1” 这一句有问题,加上这一句就报错,无法迁移之前的数据,可以去掉。
            }
        }

        private object DataBaseCreateCallBack : Callback() {
            //第一次创建数据库时调用
            override fun onCreate(db: SupportSQLiteDatabase) {
                super.onCreate(db)
                LogUtils.e("first onCreate db version: " + db.version)
            }
        }
    }

    abstract fun userDao(): UserDao
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值