Android Room使用
简介
Room库在SQLite上提供了一个抽象层,允许在充分利用SQLite的功能的同时进行更健壮的数据库访问。可以在运行的app设备上创建一个应用数据缓存,这个缓存作为app的唯一数据来源,不管用户是否有连接网络,都允许用户在app中查看相关信息。
Room有三个主要的组成部分:Database,Entity,DAO。
Database:数据库容器,并作为到应用程序的持久关系数据的底层连接的主要访问点。
使用@Database注释的类应该满足以下条件:
- 扩展RoomDatabase的抽象类
- 在注释中包含与数据库关联的实体列表
- 包含一个具有0个参数的抽象方法,并返回用@Dao注释的类
在运行时,您可以通过调用Room.databaseBuilder()或Room.inMemoryDatabaseBuilder()来获取数据库实例。
- Entity:表示数据库中的表。
- DAO:包含用于访问数据库的方法。
Room不同组成的相关关系图
引用
在project的build.gradle添加google的maven仓库
allprojects {repositories {google()jcenter()}
}
在module的build.gradle添加Room的引用,Room还提供了Rxjava2和Guava的数据处理
dependencies {def room_version = "2.1.0-alpha07"implementation "androidx.room:room-runtime:$room_version"annotationProcessor "androidx.room:room-compiler:$room_version" // For Kotlin use kapt instead of annotationProcessor// optional - Kotlin Extensions and Coroutines support for Roomimplementation "androidx.room:room-ktx:$room_version"// optional - RxJava support for Roomimplementation "androidx.room:room-rxjava2:$room_version"// optional - Guava support for Room, including Optional and ListenableFutureimplementation "androidx.room:room-guava:$room_version"// Test helperstestImplementation "androidx.room:room-testing:$room_version"
}
Enity
下面定义一个User的实体
@Entity
data class User(@PrimaryKey val uid: Int,@ColumnInfo(name = "first_name") val firstName: String?,@ColumnInfo(name = "second_name") val secondName: String?,@Ignore val desc: String?
)
- **表名:**Room使用实体类的名字作为数据库表的名字,如果想更改表名,可以使用@Entity(tableName = “users”)更改。
- **主键:**每个实体都需要定义最少一个主键,可以直接在字段使用@PrimaryKey标注主键,想Room分配自动ID可使用autoGenerate属性,也可以使用复合主键@Entity(primaryKeys = [“second_name”,“first_name” ])
- **字段名:**字段的名字默认的也是类中属性的名字如果想设置其他名字,可使用@ColumnInfo(name = “first_name”),Room为每个字段在表中创建对应的字段;如果其中一些属性不想被创建在表中怎么办,那就是使用 @Ignore 注解此属性
- **索引和唯一约束:**使用 @Entity 的 indices 来创建索引,并列出索引或者组合索引包含的列,可以使用unique属性设置唯一约束Index(value = [“name”], unique = true)
@Entity(indices = [Index("name"), Index(value = ["first_name", "second_name"])])
data class User(@PrimaryKey val uid: Int,@ColumnInfo(name = "first_name") val firstName: String?,@ColumnInfo(name = "second_name") val secondName: String?,@Ignore val desc: String?
)
- **外键:**可以使用@ForeignKey 定义对象间的级联操作
@Entity(foreignKeys = [ForeignKey(entity = User::class, parentColumns = ["uid"], childColumns = ["user_id"])])
data class Order(@PrimaryKey val orderNo: String,@ColumnInfo val address: String,@ColumnInfo(name = "user_id") val userId: Int
)
- **嵌套对象:**可以使用@Embedded 嵌套其他实体对象,可以通过设置属性 prefix 加前缀的方式保证字段名不重复。
@Embedded(prefix = "order") val order: Order?
DAO
定义一个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 second_name LIKE :last LIMIT 1 ")fun findByName(first: String, last: String): User@Insertfun insertAll(vararg users: User)@Deletefun delete(user: User)@Updatefun updateUsers(vararg users: User)
}
- **插入:**使用@Insert注解,Room将把所有的参数在一次事物中插入到数据库中,Insert的参数onConflict用来指定当发生冲突是的策略。比如将@Index的unique属性设置为true,当产生冲突时,默认情况下为OnConflictStrategy.ABORT会导致崩溃,这里设置为OnConflictStrategy.REPLACE,当发生冲突时替换老数据
- **更新:**使用@Update注解方法,可以使用参数实体的值更新主键值和参数实体的主键相同的行
- 删除:@Delete注解方法,可以删除主键值和参数实体的主键相同的行
- 查询:@Query支持查询语句,删除语句和更新语句,不支持插入语句。传入参数使用“:参数名”来进行绑定。
- 可观察查****询
在执行查询时,想让UI在数据更改时自动更新。可以在查询方法使用 LiveData 类行的返回值。当数据更新时 Room 会自动生成所需的代码已更新LiveData。
@Query("SELECT * FROM user WHERE uid IN (:userIds)")
fun getList(userIds: IntArray): LiveData<List<User>>
- 响应查询
可以从定义的查询中返回 RxJava2 的 Publisher 和 Flowable 对象
@Query("SELECT * FROM user where first_name LIKE :first AND second_name LIKE :last LIMIT 1 ")
fun getByName(first: String, last: String): Flowable<User>
Database
@Database(entities = arrayOf(User::class), version = 1)
abstract class AppDatabase : RoomDatabase() {abstract fun userDao(): UserDao
}
创建完完成后使用以下代码获取数据库实例,并且使用单例来访问
var db = Room.databaseBuilder(getApplicationContext(),AppDatabase::class.java, "database-name"
).build()
迁移数据库
在APP升级时可能需要更改数据库来策应新的功能。如果不希望数据库中的数据丢失,
Room 允许我们编写 Migration ,以此来迁移数据;如果使用fallbackToDestructiveMigration(),数据库的内容都被清空。
每个迁移类制定一个开始版本和结束版本。在运行时,Room会运行每个Migration类的migrate()方法,并使用正确的顺序将数据库迁移到更高版本。
首先,需要更新Database的版本号
@Database(entities = arrayOf(User::class), version = 2)
abstract class AppDatabase : RoomDatabase() {abstract fun userDao(): UserDao
}
其次添加一个version:1->2的migration
val MIGRATION_1_2: Migration = object : Migration(1, 2) {override fun migrate(database: SupportSQLiteDatabase) {database.execSQL("ALTER TABLE User " + " ADD COLUMN mobile TEXT")}
}
最后把migration 添加到 databaseBuilder,addMigrations提供可选参数,支持多版本迁移,传入多个migration。
var db = Room.databaseBuilder(getApplicationContext(),AppDatabase::class.java, "database-name"
).allowMainThreadQueries().addMigrations(MIGRATION_1_2).build()
Room的基本用法介绍已经END。
Android Room使用相关推荐
- Unity5.6+ 导出Android 应用程序apk的环境配置及导出过程
首先下载并安装安卓SDK和java的JDK 安卓sdk下载: http://www.android-studio.org/ 也可以在这下载: 链接:http://pan.baidu.com/s/1bp ...
- Android 的NDK的Makefile编写
Android.mk 是google根据Linux GNU Makefile精简编译脚本.具体来说:这就是GNU Makefile的一小部分. 举一个简单例子: LOCAL_PATH := $(cal ...
- Android Animation (安卓动画)概念简介
Android Animation Android 四种动画分别为逐帧动画和补间动画.属性动画.过渡动画: Frame Animation (逐帧动画) 实现方式:xml 和 Java代码 图片跳转的 ...
- 基于Android和SpringBoot的购物App
(Shopping)购物应用商城 本软件使用Android和SpringBoot.JavaWeb技术实现:并结合百度LBS平台的SDK.支付宝App支付客户端SDK.MobTech的ShareSDK: ...
- Android数据持久化:SharePreference
SharePreference:作为Android数据持久化的一种,具有一定的便捷性,适合存储一些体积小的数据. 存储数据方式:键值对的方式,类似于Map: 利用SharePreference.Edi ...
- Android数据持久化:文件存储
数据持久化: 数据可分为瞬时数据和关键数据.保存在内存之中的数据是瞬时数据,而对于一些关键性数据,后期需要持续使用的,应当保存在存储设备中: 持久化保存方式: 文件存储.SharePreference ...
- Android Studio中RecycerView依赖库加载问题
依赖包导入思考: 参考资料:recycleview导包问题 打开修改本项目中的build.gradle; 切勿着急添加包,应当提前查看其中的版本号(因为加载的v7包要和其版本保持一致性): 例如: 因 ...
- Android布局优化之include、merge、ViewStub
include:引入重复使用的相同布局 merge:减少include布局的层级,将子元素直接添加到merge标签的parent中 ViewStub:其实就是一个宽高都为0的一个View,它默认是不可 ...
- Android动画之帧动画和补间动画
Android系统提供三种动画:帧动画.补间动画和属性动画.这里先分析总结帧动画和补间动画. FrameAnimation 帧动画,通俗来说就是按照图片动作顺序依次播放来形成动画,创建帧动画可以用 x ...
- Android系统的启动过程
Android系统的启动过程可以简单地总结为以下几个流程: 加载BootLoader -> 初始化内核 -> 启动init进程 -> init进程fork出Zygote(孵化器)进程 ...
最新文章
- R语言定量变量组间差异检验
- python3 issubset 判断列表子集
- 16.异常处理机制:exception
- 【Pytorch神经网络基础理论篇】 01 从零开始介绍深度学习算法和代码实现
- tomcat 9 无法启动_运维常见问题汇总tomcat篇
- Python 标准库 —— 文件解压(zip、gz、pkl、tar)
- python和c++哪个好-python和C++语言哪个好?老男孩教育
- [CQOI2015]选数
- WPF的错误以及笔记
- 封装出现 用户.计算机,系统封装教程 会电脑就会封装 | 一堵墙
- 【狂神说】Spring学习笔记(全)
- PDF转CAD格式步骤再简单
- 如何解决ueditor乱码问题
- Unity Predefined assemblies/assembly definition files
- 半导体技术科普:解读第三代半导体及宽禁带半导体
- Jest测试语法系列之Expect
- 110道python面试笔试题汇总,你能答对几道?
- 撩课小程序(教育类)实战存档(小程序 + 云开发)
- ROS wiki learn 整理 1
- 笔记本Win10超简单hdmi线链接树莓派