这一篇我们主要介绍下
Room
数据库的创建以及简单使用
Room
介绍
Room
是Google为了简化SQLite
推出的
拥有SQLite
所有的操作功能;
使用简单,通过注解方式实现功能,类似Retrofit
,编译时自动生成实现类
与LiveData
,LifeCycle
,Paging
天然融合
Room
使用
添加依赖
implementation "android.arch.persistence.room:runtime:1.1.1"
annotationProcessor 'android.arch.persistence.room:compiler:1.1.1'
使用
我们先新建一个类
CacheDatabase
,同时继承RoomDatabase
public class CacheDatabase extends RoomDatabase {
}
这里我们看见AS提示我们需要实现
RoomDatabase
的一些方法,但是我们可以把这个类声明为abstract
类型,为啥呢?因为我们刚才介绍过Room
是通过注解实现功能,编译时用通过annotationProcessor
来帮我们实现实现类,所以在我们编译的时候会生成CacheDatabase
的实现类,这样我们就不用复写RoomDatabase
几个默认的方法了
public abstract class CacheDatabase extends RoomDatabase {
}
接着我们对我们这个
Database
进行初始化,我们还是在静态代码块中实现创建数据库有两种
第一种:
//创建一个内存数据库
//但是这种数据库的数据只存在于内存中,也就是进程被杀之后,数据随之丢失
Room.inMemoryDatabaseBuilder()
这种我们一般不会使用,所以我们一般都是用下面这种方式
Room.databaseBuilder(AppGlobals.getApplication(), CacheDatabase.class, "joke_video_cache")
我们看下这个方法源码
@SuppressWarnings("WeakerAccess")
@NonNull
public static RoomDatabase.Builder databaseBuilder(
@NonNull Context context, @NonNull Class klass, @NonNull String name) {
//noinspection ConstantConditions
if (name == null || name.trim().length() == 0) {
throw new IllegalArgumentException("Cannot build a database with null or empty name."
+ " If you are trying to create an in memory database, use Room"
+ ".inMemoryDatabaseBuilder");
}
return new RoomDatabase.Builder(context, klass, name);
}
第一个参数是上下文;第二个参数是使用
Database
注解标记并且继承RoomDatabase
的类;第三个是数据库名字所以我们还需要把我们这个类用
Database
标记下我们需要配置三个属性,第一个就是我们要操作的类,可以是多个;第二个是数据库的版本号;第三个是存储展示数据库的结构信息,默认是true,如果设置为true,我们需要设置 Schema 的位置
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
defaultConfig {
//......
javaCompileOptions{
annotationProcessorOptions{
arguments=["room.schemaLocation":"$projectDir/schemas".toString()]
}
}
}
//......
}
因为我们还没有
Entity
类,所以我们创建一个
@Entity(tableName = "cache")
public class Cache implements Serializable {
@PrimaryKey(autoGenerate = false)
public String key;
@ColumnInfo(name = "data")
public byte[] data;
}
这里需要使用
Entity
注解标记,可以给他指定表名,也可以使用默认;PrimaryKey
注解的变量为主键,autoGenerate
表示主键的值是否由Room
自动生成,默认false
;ColumnInfo
表示数据控存这个属性的名字,同时我们给它指定两个属性key
和data
,key
是我们以后查询缓存要使用的,data
表示我们要缓存的数据,因为我们不确定缓存什么类型,所以统一使用二进制数组
接着我们回到我们刚才的
CacheDatabase
,我们完善下它头部的注解
@Database(entities = {Cache.class},version = 1,exportSchema = true)
public abstract class CacheDatabase extends RoomDatabase {
}
我们通过
Room.databaseBuilder
创建出一个RoomDatabase.Builder
对象,接下来我们就简单说下它的配置
Room.databaseBuilder(AppGlobals.getApplication(), CacheDatabase.class, "joke_video_cache")
//是否允许在主线程进行查询
//.allowMainThreadQueries()
//数据库创建和打开后的回调
//.addCallback()
//设置查询的线程池
//.setQueryExecutor()
//.openHelperFactory()
//room的日志模式
//.setJournalMode()
//数据库升级异常之后的回滚
//.fallbackToDestructiveMigration()
//数据库升级异常后根据指定版本进行回滚
//.fallbackToDestructiveMigrationFrom()
数据库升级
如果我们需要进行数据库的升级,需要在配置数据库的时候调用
addMigrations
方法,我们先看下源码
@NonNull
public Builder addMigrations(@NonNull Migration... migrations) {
if (mMigrationStartAndEndVersions == null) {
mMigrationStartAndEndVersions = new HashSet();
}
for (Migration migration: migrations) {
mMigrationStartAndEndVersions.add(migration.startVersion);
mMigrationStartAndEndVersions.add(migration.endVersion);
}
mMigrationContainer.addMigrations(migrations);
return this;
}
入参是多个
Migration
对象,我们看下Migration
的构造方法也就是说我们指定多个版本升级的操作,例如
数据库操作
数据库操作我们需要使用
Dao
这个注解,这里我们新建一个CacheDao
类,同时实现增,删,改,查方法,因为只有查比较麻烦,所以我们可以写一个基类BaseDao
,里面含有增,删,改方法,然后我们的CacheDao
,继承BaseDao
@Dao
public interface BaseDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertItem(T item);//插入单条数据
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertItems(List items);//插入list数据
@Delete
void deleteItem(T item);//删除item
@Update(onConflict = OnConflictStrategy.REPLACE)
void updateItem(T item);//更新item
}
@Dao
public interface CacheDao extends BaseDao{
//如果是一对多,这里可以写List
@Query("select *from cache where `key`=:key")
Cache getCache(String key);
}
作者:Greathfs