Jetpack学习之Room

2023-11-01

Android采用sqlite作为数据库存储,Room就是Google推出的自己的ORM(Object Relational Mapping)。
Room的架构图:
Room架构图

  • Entity:一个Entity对应于数据库中的一张表。Entity类是Sqlite表结构对Java类的映射,在Java中可以被看作一个Model类。
  • Dao:即Data Access Objects,数据访问对象,可以通过它来访问数据。
    一个Entity代表一张表,而每张表都需要一个Dao对象,用于对表进行增/删/改/查。Room数据库在被实例化之后,可以通过数据实例得到Dao对象(Get Dao),进而通过Dao对象对表中的数据进行操作。
使用Room
  1. 在app的build.gradle中添加Room的相关依赖
    implementation 'androidx.room:room-runtime:2.2.5'
    kapt "androidx.room:room-compiler:2.2.5"
  1. 创建一个Entity,即一张表。新建一个类文件,并在类文件的上方添加@Entity标签。
@Entity(tableName = "student")
data class Student(

    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "id", typeAffinity = ColumnInfo.INTEGER)
    var id: Int?,

    @ColumnInfo(name = "name", typeAffinity = ColumnInfo.TEXT)
    var name: String?,

    @ColumnInfo(name = "age", typeAffinity = ColumnInfo.TEXT)
    var age: String?
)
  • @Entity标签用于将Student类与Room中的数据表对应起来。tableName属性可以位数据表设置表名,若不设置,则表名与类名相同。
  • @PrimaryKey标签用于指定该字段作为表的主键
  • @ColumnInfo标签可用于设置该字段存储在数据库表中的名字,并指定字段类型。
  • @Ignore标签用来告诉Room忽略该字段或方法。
  1. 针对上面的Entity,需要定义一个Dao接口文件,以便于对Entity进行访问。需要在文件上方添加@Dao标签。
@Dao
interface StudentDao {
    @Insert
    fun insertStudent(student: Student)

    @Delete
    fun deleteStudent(student: Student)

    @Update
    fun updateStudent(student: Student)

    @Query("SELECT * FROM student")
    fun getStudentList(): LiveData<List<Student>>

    @Query("SELECT * FROM student WHERE id = :id")
    fun getStudentById(id: Int)
}
  1. 定义好Entity和Dao后,接下来创建数据库。
const val MY_DATABASE_NAME = "my_db"

@Database(entities = [Student::class], version = 1)
abstract class MyDatabase : RoomDatabase() {

    companion object {
        val instance = Single.sin
    }

    private object Single {
        val sin: MyDatabase =
            Room.databaseBuilder(MyApplication.instance(), MyDatabase::class.java, MY_DATABASE_NAME)
                .build()

    }

    abstract fun studentDao(): StudentDao
}
@Database标签用于告诉系统这是Room数据库对象。entities属性用于指定该数据库有哪些表,若需要建立多张表,则表名以逗号相隔开;version属性用于指定数据库版本号,数据库升级依据版本号进行判断。
数据库类需要继承自RoomDatabase,并通过Room.databaseBuilder()结合单例设计模式完成创建。
  1. 数据库和表创建完成后,就可以通过单例模式调用数据库进行增/删/改/查,接口调用时需要注意线程切换。
与LiveData、ViewModel结合使用


当Room数据库中的数据发生变化时,通过LiveData组件通知View层,实现数据的自动更新。

class StudentViewModel(application: MyApplication): AndroidViewModel(application) {
    private val myDatabase = MyDatabase.instance

    val liveDataStudent = myDatabase.studentDao().getStudentList()

}
private val studentViewModel: StudentViewModel by viewModels()
studentViewModel.liveDataStudent.observe(viewLifecycleOwner, {
    students -> { TODO("显示students列表")}
})
数据库升级

Android提供了一个名为Migration的类来对Room进行升级。

    public Migration(int startVersion, int endVersion) {
        this.startVersion = startVersion;
        this.endVersion = endVersion;
    }

Migration有两个参数,startVersion和endVersion,startVersion表示当前数据库版本,endVersion表示将要升级到的版本。

val MIGRATION_1_2 = object : Migration(1, 2) {
            override fun migrate(database: SupportSQLiteDatabase) {
                TODO("执行升级相关操作")
            }
        }

在Migration中编写完升级方案后,需要通过addMigrations()方法,将升级方案添加到Room。

Room.databaseBuilder(MyApplication.instance(), MyDatabase::class.java, MY_DATABASE_NAME)
                .addMigrations(MIGRATION_1_2)
                .build()
异常处理

Room在升级过程中没有匹配到相应的Migration,会导致应用程序崩溃,可以在创建数据库时加入fallbackToDestructiveMigration()方法,此方法能在升级异常时,重新创建数据表。但需要注意,虽然应用程序不会崩溃,但所有数据会丢失。

Room.databaseBuilder(MyApplication.instance(), MyDatabase::class.java, MY_DATABASE_NAME)
    .addMigrations(MIGRATION_1_2)
    .fallbackToDestructiveMigration()
    .build()
Schema文件

Room提供了一项功能,在每次数据库升级的过程中,会导出一个Schema文件,这是一个json格式的文件,其中包含了数据库的所有基本信息。
可以在app的build.gradle文件中指定schema文件的导出位置。

javaCompileOptions {
        annotationProcessorOptions {
            arguments = ["room.schemaLocation":"$projectDir/ schemas".toString()]
        }
    }

Room默认导出Schema文件,如果不想导出,可以在数据库标签@Database中指定exportSchema=false

销毁与重建策略
  1. 创建一张符合表结构要求的临时表temp
  2. 将数据从旧表复制到临时表temp
  3. 删除旧表
  4. 将临时表temp重命名为原表名
预填充数据

如果已有数据库文件.db,可以放到assets目录下,然后使用createFromAsset()方法创建Room数据库;或者将.db文件放到SD卡下,使用createFromFile()方法来创建Room数据库。

Room.databaseBuilder(MyApplication.instance(), MyDatabase::class.java, MY_DATABASE_NAME)
    .addMigrations(MIGRATION_1_2)
    .fallbackToDestructiveMigration()
    .createFromAsset("database/students.db")
    .build()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Jetpack学习之Room 的相关文章

随机推荐

  • 深度神经网络的matlab实现,深度神经网络代码matlab

    为什么不用matlab做深度学习 matlab可以做深度学习 但是从实用性的角度来讲matlab的实现效率相对较低 训练耗时较长 初次学习计算机语言就选择matlab不是一个明智的选择 最好选用C或者Basic作为入门语言 matlab是一
  • 初探C语言链表(一)

    初探链表 一 静态链表 二 动态链表 初始化链表 1 尾插法建立链表 2 头插法建立链表 三 动态链表的基本操作 1 遍历 2 查找 3 插入 4 清空 5 删除 6 销毁 四 链表的综合应用 什么是链表 链表是由一系列节点组成 每个节点包
  • 面试经验:阿里Java后台开发

    最近原来实习时候的Boss联系我 说他跳槽到了阿里 问我有没有兴趣面一个Java后台开发岗位 考虑到我只工作了一年 现在去阿里肯定要降薪 因此也没有太强烈的意愿 但出于提升自我的角度考虑 参加了面试 一面 电话面试一小时 首先做一个简单的自
  • 09虚幻4【UE4】中模型沿着轨道运动

    目录 一 创建Track蓝图类 轨道 并添加一个Spline样条曲线 二 创建TrackCar 移动车 蓝图类并添加一个Mesh 车 方块都可以 三 编写TrackCar的蓝图逻辑 3 1 设置自定义事件MoveCar 3 2 添加时间轴
  • Python全栈开发【基础-04】一文彻底理解Python变量

    专栏介绍 本专栏为Python全栈开发系列文章 技术包括Python基础 函数 文件 面向对象 网络编程 并发编程 MySQL数据库 HTML JavaScript CSS JQuery bootstrap WSGI Django Flas
  • Android手写占位式插件化框架之apk解析原理系统源码分析

    前些天发现了一个蛮有意思的人工智能学习网站 8个字形容一下 通俗易懂 风趣幽默 感觉非常有意思 忍不住分享一下给大家 点击跳转到教程 前言 上一篇文章 Android手写占位式插件化框架之Activity通信 Service通信和Broad
  • JAVA--不同包类的相互访问

    1 不同包之间的访问在定义类之前使用import 加导入的类名 2 不同包没有任何关系的两个类 只有public的类中的public成员才能被另一个包访问 package yi 第一个包 public class A public void
  • sqlserver数据库触发器,对当前的表数据插入时,根据条件防止数据重复插入。

    这是一个之前做项目用的 以下是触发器sql语句 直接执行即可 如果需求不一样需要修改对应的语句就行 USE NetCoreWebApi GO Object Trigger dbo testInsertTrigger Script Date
  • git clone 遇到问题:fatal: unable to access

    git clone 遇到问题 fatal unable to access https github com ros planning navigation git Failed to connect to 127 0 0 1 port 4
  • LeNET的学习以及代码实现

    根据李沐老师的动手深度学习的书进行学习 import torch from torch import nn net nn Sequential nn Conv2d 1 6 kernel size 5 padding 2 nn Sigmoid
  • 运营活动类项目测试方案设计

    1 背景 随着业务的不断发展成熟 商业业务逐渐向重运营 重策略的模式发展 提出的需求中运营活动类需求数量也不断增多 而通过项目的积累 与其他业务的讨论共创 我们也积累了一批对运营活动类项目的测试点和对应的测试方案 下面我将从设计思路和具体内
  • Yolov5 face训练手册

    目录 支持tensorrt yolov5 face 人脸对齐 训练标签可视化 网络特点 关于tensorboard
  • 关于CUDA计算矩阵乘法那些事情

    我想记录一下今天所做的事情 与我自己对GPU 的对矩阵加速的并行运算的认知有点背道而驰 我一共写了三个相同的并行计算程序 理论上 在cpu上面运行的应该是最慢的 用共享内存计算的那个应该是最快的 但是 结果却是与预计的相反 我得提前声明一下
  • SpringBoot在一定时间内限制接口请求次数

    需要用到的知识 注解 AOP ExpiringMap 带有有效期的映射 我们可以自定义注解 把注解添加到我们的接口上 定义一个切面 执行方法前去ExpiringMap查询该IP在规定时间内请求了多少次 如超过次数则直接返回请求失败 需要用到
  • unity属性面板值的显示和隐藏

    Serialize功能 Unity3D 中提供了非常方便的功能可以帮助用户将 成员变量 在Inspector中显示 并且定义Serialize关系 简单的说 在没有自定义Inspector的情况下所有显示在Inspector 中的属性都同时
  • ROS里程计消息nav_msgs/Odometry的可视化方法

    ROS中里程计的消息类型为nav msgs Odometry 该消息类型具有以下结构 可以看到 里程计消息中的pose包含了位置pose position和姿态pose orientation 在ROS中 有一种常用消息类型为nav msg
  • discuz 配置https

    下面我就不同版本来给大家讲解下如何修改源文件来支持https discuz X2 0 x2 0的版本用的人不多了 但我这里还是提供一份X2 0的https改造教程 https www aitiancheng com article 550
  • Dart

    Dart 是一种跨平台的客户端开发语言 具有专门为客户端优化 高生产力 快速高效 可移植易学的风格 Dart主要由Google负责开发和维护 构造函数 命名构造函数 默认构造函数 私有属性需要加 并且是单独的文件才可以 也可以通过公员有方法
  • gcc编译过程理解

    GNU CC 通常称为GCC 是GNU项目的编译器 它能够编译C C 语言编写的程序 使用gcc 程序员可以对编译过程有更多的控制 编译过程分为3个阶段 预处理 汇编 链接 程序员可以再编译的任何阶段结束后停止整个编译过程以检查编译器在该阶
  • Jetpack学习之Room

    Android采用sqlite作为数据库存储 Room就是Google推出的自己的ORM Object Relational Mapping Room的架构图 Entity 一个Entity对应于数据库中的一张表 Entity类是Sqlit