1、前言
最近简单看了下google推出的框架Jetpack,感觉此框架的内容可以对平时的开发有很大的帮助,也可以解决很多开发中的问题,对代码的逻辑和UI界面实现深层解耦,打造数据驱动型UI界面。
Android Architecture组件是Android Jetpack的一部分,它们是一组库,旨在帮助开发者设计健壮、可测试和可维护的应用程序,包含一下组件:
- 带你领略Android Jetpack组件的魅力
- Android Jetpack 架构组件之 Lifecycle(使用篇)
- Android Jetpack 架构组件之 Lifecycle(源码篇)
- Android Jetpack 架构组件之 ViewModel (源码篇)
- Android Jetpack 架构组件之 LiveData(使用、源码篇)
- Android Jetpack架构组件之 Paging(使用、源码篇)
- Android Jetpack 架构组件之 Room(使用、源码篇)
- Android Jetpack 架构组件之Navigation
- Android Jetpack架构组件之WorkManger
- 实战:从0搭建Jetpack版的WanAndroid客户端
上述时Android Architecture所提供的架构组件,本文主要从使用和源码的角度分析Room组件。
2、Room 简介
Room是Google提供的一个ORM库。Room提供了三个主要的组件:
- @Database:@Database用来注解类,并且注解的类必须是继承自RoomDatabase的抽象类。该类主要作用是创建数据库和创建Daos(data access objects,数据访问对象)。
- @Entity:@Entity用来注解实体类,@Database通过entities属性引用被@Entity注解的类,并利用该类的所有字段作为表的列名来创建表。
- @Dao:@Dao用来注解一个接口或者抽象方法,该类的作用是提供访问数据库的方法。在使用@Database注解的类中必须定一个不带参数的方法,这个方法返回使用@Dao注解的类
3、Room数据库使用
数据库的创建
- 包含数据库持有者,并作为应用程序持久关系数据的基础连接的主要访问点,使用@Database注解,注解类应满足以下条件:
- 数据库必须是一个抽象类 RoomDatabase的扩展类
- 在注释中包括与数据库关联的实体列表
- 必须包含一个具有0个参数且返回带@Dao注释的类的抽象方法
- 通过调用 Room.databaseBuilder()或 获取实例Room.inMemoryDatabaseBuilder()创建数据库实例
- 使用单例实例化数据库对象
@Database(entities = {User.class}, version = 1) // 注释
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao(); // 抽象方法
}
- 以单例形式对外提供RoomDataBase实例
public static UserDataBase getInstance(Context context) {
if (userDataBase == null) {
synchronized (UserDataBase.class) {
if (userDataBase == null) {
userDataBase = Room.databaseBuilder(context.getApplicationContext()
, UserDataBase.class, "user_data").build();
}
}
}
return userDataBase;
}
定义实体数据:表示数据库中的表
- @Entity
- 使用@Entity注解实体类,Room会为实体中定义的每个字段创建一列,如果想避免使用@Ignore注解
- Room默认使用类名作为数据库表名,要修改表名使用 @Entity 的 tableName属性
- 主键
- @PrimaryKey :至少定义一个字段作为主键
- 如果自增长ID 使用设置@PrimaryKey的 autoGenerate 属性
- 使用组合主键 使用@Entity 的@primaryKeys属性
- Room 默认使用字段名成作为列名,要修改使用 @ColumnInfo(name = "***")
@Entity(tableName = "userDataBase")
class User {
@PrimaryKey(autoGenerate = true) // 单个主键设置为自增长
public var id = 0
@ColumnInfo(name = "nameUser") // 定义列名
public var name: String? = null
}
@Entity(primaryKeys = ["id", "name"]) // 组合组件
- 添加索引@Entity
- 使用 @Entity 的indices 属性,列出要包含在索引或复合索引中的列的名称
@Entity(indices = [Index("nameUser"), Index(value = ["name"])]) // 创建索引
@Entity(indices = [Index("nameUser"), Index(value = ["name"] ,unique = true)]) //唯一索引
- 外键约束@ForeignKey
- 使用@ForeignKey 注释定义其与实体的 关系;ForeignKey中 entity 为要关联的父实体类;parentColumns 为关联父实体类的列名;childColumns此实体类中的列名
@Entity(foreignKeys = [ForeignKey(entity = User::class,
parentColumns = ["id"],
childColumns = ["user_id"])])
class Book {
@PrimaryKey
var bookId: Int = 0
var title: String? = null
@ColumnInfo(name = "user_id")
var userId: Int = 0
}
- 嵌套对象@Embedded
- 使用 @Embedded 注释来表示要分解到表中子字段的对象(此时数据库的列为两个类中所有的字段)
class Address {
public var street: String? = null
public var state: String? = null
public var city: String? = null
@ColumnInfo(name = "post_code")
public var postCode =