使用Room封装本地数据

518 阅读4分钟

1.为什么使用Room

Room 持久性库在SQlite的基础上提供了一个抽象成,让用户能够充分利用 SQLite 的强大功能的同时,获享强健的数据库访问机制.它可用来避免样板代码,还可以轻松地将 SQLite 表数据转换为 Java 对象。Room 提供 SQLite 语句的编译时检查,并且可以返回 RxJava、Flowable 和 LiveData 可观察对象,使用ROOM可以让你更简单,更流畅的操作数据库,使用简单通过注解的方式就能对数据库进行增删改查,Google工程师帮你封装了访问SqlLite的代码,使你的代码性能更高

2. Room 各组件间关系

Room 的大致使用方法如下:

  • App 通过 Room 的 Database 获取与数据库相关的数据库访问对象(DAO)。

  • 然后,App 使用 DAO 从数据库中获取 Entity,并且将 Entity 的变化保存到数据库中。

  • 最后,APP 使用 Entity 获取和设置数据库中表的数据。

Room 中各组件之间的关系如图2- 1Room 架构图所示:

image.png

3.使用(Java版)

3.1添加依赖

dependencies {
    val room_version = "2.5.0"

    implementation("androidx.room:room-runtime:$room_version")
    annotationProcessor("androidx.room:room-compiler:$room_version")

    // To use Kotlin annotation processing tool (kapt)
    kapt("androidx.room:room-compiler:$room_version")
    // To use Kotlin Symbol Processing (KSP)
    ksp("androidx.room:room-compiler:$room_version")

    // optional - Kotlin Extensions and Coroutines support for Room
    implementation("androidx.room:room-ktx:$room_version")

    // optional - RxJava2 support for Room
    implementation("androidx.room:room-rxjava2:$room_version")

    // optional - RxJava3 support for Room
    implementation("androidx.room:room-rxjava3:$room_version")

    // optional - Guava support for Room, including Optional and ListenableFuture
    implementation("androidx.room:room-guava:$room_version")

    // optional - Test helpers
    testImplementation("androidx.room:room-testing:$room_version")

    // optional - Paging 3 Integration
    implementation("androidx.room:room-paging:$room_version")
}

3.2创建实体类,这里就不缀述了,大部分都知道如何创建(具体可以参考官方文档) 主要使用到

@Entity//表
@PrimaryKey(autoGenerate = true)//主键唯一,自增长
@ColumnInfo(name = "age")//优先使用这个

3.3创建Dao

@Insert
void insertWords(实体类... 实体类变量名);//10条数据

@Update
void updateWords(实体类... 实体类变量名);

//条件删除
@Delete
void deleteWords(实体类... 实体类变量名);

//全部删除
@Query("DELETE FROM 实体类")
void deleteAllWords();

//查询全部
@Query("SELECT * FROM 实体类 ORDER BY ID DESC")

 LiveData<List<实体类>> getAllStudentLive();

3.2 创建数据库

@Database(entities = {实体类.class}, version = 1, exportSchema = false)
public abstract class 实体类Database extends RoomDatabase {
    private static 实体类Database INSTANCE;

    public static synchronized 实体类Database getDatabase(Context context) {
        if (INSTANCE == null) {
            INSTANCE = Room.databaseBuilder(context.getApplicationContext(),实体类Database.class,"实体类_database")
//                    .allowMainThreadQueries()//允许在主线程运行(慎用,google不推荐)
                    .build();
        }
        return INSTANCE;
    }


    public abstract 实体类Dao get实体类Dao();
}

3.3本地仓库统一管理类


public class LocalRoomResquestManager implements ILocalRequest, IDatabaseRequest {
    private static LocalRoomResquestManager INSTANCE;
    private 实体类Dao m实体类Dao;
    private LiveData<List<实体类>> studentsLive;

    public LocalRoomResquestManager(Context context) {
        实体类Database m实体类Database = 实体类Database.getDatabase(context.getApplicationContext());
        m实体类Dao = m实体类Database.get实体类Dao();
        实体类Live = m实体类Dao.getAll实体类Live();
    }

    public static LocalRoomResquestManager getInstance(Context context) {
        if (null == INSTANCE) {
            synchronized (LocalRoomResquestManager.class) {
                if (null == INSTANCE) {
                    INSTANCE = new LocalRoomResquestManager(context);
                }
            }
        }
        return INSTANCE;
    }

    @Override
    public LiveData<List<实体类>> get实体类Live() {
        return studentsLive;
    }

    @Override
    public void insert实体类s(实体类... 实体类变量名) {
        new InsertAsyncTask(实体类Dao).execute(实体类变量名);
    }

    @Override
    public void update实体类s(实体类... 实体类变量名) {
        //.....自己的执行逻辑
    }

    @Override
    public void delete实体类s(实体类... 实体类变量名) {
         //.....自己的执行逻辑
    }


    @Override
    public void deleteAll实体类s() {
        new DeleteAllAsyncTask(实体类Dao).execute();
    }

    static class InsertAsyncTask extends AsyncTask<实体类, Void, Void> {
        private 实体类Dao m实体类Dao;

        public InsertAsyncTask(实体类Dao m实体类Dao) {
            this.m实体类Dao = m实体类Dao;
        }

        @Override
        protected Void doInBackground(实体类... 实体类变量名) {
            studentDao.insertWords(实体类变量名);
            return null;
        }
    }


    static class DeleteAllAsyncTask extends AsyncTask<Void, Void, Void> {
        private 实体类Dao m实体类Dao;

        public DeleteAllAsyncTask(实体类Dao m实体类Dao) {
            this.m实体类Dao = m实体类Dao;
        }

        @Override
        protected Void doInBackground(Void... voids) {
            studentDao.deleteAllWords();
            return null;
        }
    }

}

3.4本地仓库统一管理类viewmolde的使用

public LiveData<List<Student>> get实体类Live() {
    return LocalRoomResquestManager.getInstance(application).get实体类Live();
}

public void touchoffInsertStudents(实体类... 实体类变量名) {
    LocalRoomResquestManager.getInstance(application).insert实体类s(实体类变量名);

}

public void touchoffDeleteAllWords() {
    LocalRoomResquestManager.getInstance(application).deleteAllStudents();
}

3.5在activiry中或者fragment中的使用,这里调用就不再赘述了

4# 解决:cannot find implementation for XXX. XXX_Impl does not exist

第一次使用Jetpack上Room架构,遇到一个问题Caused by: java.lang.RuntimeException: cannot find implementation for com.aheading.request.database.AppDatabase. AppDatabase_Impl does not exist ,就是如下这个错误:

image.png

4.1检查注解是否添加

确保注解是否都已经添加,并且确保注解内容是否正确.

  • @Database:表示数据库.

  • @Entity:表示数据库中的表。

  • @DAO:包含用于访问数据库的方法。
    如果注解添加错误也会有以上错误。

4.2检查依赖是否添加

//Android官网依赖是这样的,java开发人员使用
    compile "android.arch.persistence.room:runtime:$room_version"
    annotationProcessor 'android.arch.persistence.room:compiler:$room_version'

    //对于那些使用Kotlin的人,请尝试在应用中更改annotationProcessor为kapt
    compile "android.arch.persistence.room:runtime:$room_version"
    kapt "android.arch.persistence.room:compiler:$room_version"

    //如果您已迁移到androidx
    implementation "androidx.room:room-runtime:$room_version"
    implementation "androidx.room:room-ktx:$room_version"
    kapt "androidx.room:room-compiler:$room_version"

如果使用了kotlin项目,不要忘记在顶部引用kotlin-kapt插件

apply plugin: 'kotlin-kapt'

4.3 是否是多模块x项目

如果项目包含多个模块,在使用RoomDataBase的那个模块中,同样需要添加kapt依赖。

apply plugin: 'kotlin-kapt'


dependencies {
          kapt  "androidx.room:room-compiler:$room_version"
}