【Android】Jetpack全组件实战开发短视频应用App(六)

前言

项目地址
这一篇我们主要介绍下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 {
}

【Android】Jetpack全组件实战开发短视频应用App(六)_第1张图片
这里我们看见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")

我们看下这个方法源码

 /**
     * Creates a RoomDatabase.Builder for a persistent database. Once a database is built, you
     * should keep a reference to it and re-use it.
     *
     * @param context The context for the database. This is usually the Application context.
     * @param klass   The abstract class which is annotated with {@link Database} and extends
     *                {@link RoomDatabase}.
     * @param name    The name of the database file.
     * @param      The type of the database class.
     * @return A {@code RoomDatabaseBuilder} which you can use to create the database.
     */
    @SuppressWarnings("WeakerAccess")
    @NonNull
    public static <T extends RoomDatabase> RoomDatabase.Builder<T> databaseBuilder(
            @NonNull Context context, @NonNull Class<T> 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标记下
【Android】Jetpack全组件实战开发短视频应用App(六)_第2张图片
我们需要配置三个属性,第一个就是我们要操作的类,可以是多个;第二个是数据库的版本号;第三个是存储展示数据库的结构信息,默认是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表示数据控存这个属性的名字,同时我们给它指定两个属性keydata,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方法,我们先看下源码

 /**
         * Adds a migration to the builder.
         * 

* Each Migration has a start and end versions and Room runs these migrations to bring the * database to the latest version. *

* If a migration item is missing between current version and the latest version, Room * will clear the database and recreate so even if you have no changes between 2 versions, * you should still provide a Migration object to the builder. *

* A migration can handle more than 1 version (e.g. if you have a faster path to choose when * going version 3 to 5 without going to version 4). If Room opens a database at version * 3 and latest version is >= 5, Room will use the migration object that can migrate from * 3 to 5 instead of 3 to 4 and 4 to 5. * * @param migrations The migration object that can modify the database and to the necessary * changes. * @return this */ @NonNull public Builder<T> 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的构造方法
【Android】Jetpack全组件实战开发短视频应用App(六)_第3张图片
也就是说我们指定多个版本升级的操作,例如
【Android】Jetpack全组件实战开发短视频应用App(六)_第4张图片

数据库操作

数据库操作我们需要使用Dao这个注解,这里我们新建一个CacheDao类,同时实现增,删,改,查方法,因为只有查比较麻烦,所以我们可以写一个基类BaseDao,里面含有增,删,改方法,然后我们的CacheDao,继承BaseDao

@Dao
public interface BaseDao<T> {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void insertItem(T item);//插入单条数据

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void insertItems(List<T> items);//插入list数据

    @Delete
    void deleteItem(T item);//删除item

    @Update(onConflict = OnConflictStrategy.REPLACE)
    void updateItem(T item);//更新item
}
@Dao
public interface CacheDao extends BaseDao<Cache>{

    //如果是一对多,这里可以写List
    @Query("select *from cache where `key`=:key")
    Cache getCache(String key);
}

你可能感兴趣的:(Jetpack)