关于Android架构组件Room的简单使用

前言:Room于2017年谷歌IO大会上被推出,当时伴随着推出的还有LiveData以及ViewModel。相比于如今Ormlite、GreenDao等框架的优势,Room自带支持LiveData与ViewModel。这篇文章只是简单的介绍下Room的使用,并不涉及LiveData与ViewModel的组合使用。后续文章再加上吧。

废话不多说,进入正题。

首先,导入使用Room

implementation 'android.arch.persistence.room:runtime:1.0.0'
annotationProcessor 'android.arch.persistence.room:compiler:1.0.0'

使用Room的关键有三点:

Entity:使用Architecture Components时,这是一个带注释的类,用于描述数据库表。

SQLite database在设备上,数据存储在SQLite数据库中。Room持久性库为您创建和维护此数据库。

DAO: data access object(数据访问对象)。SQL查询到函数的映射。当您使用DAO时,您可以调用方法,而Room负责其余的操作。

我们先创建Entity:

@Entity(tableName = "info")
public class InfoEntity {

    @PrimaryKey(autoGenerate = true)
    public int _id;

    @ColumnInfo(name = "uuid")
    private String uuid;

    private String info;

    public InfoEntity(String info) {
        uuid = UUID.randomUUID().toString();
        this.info = info;
    }

    public String getUuid() {
        return uuid;
    }

    public void setUuid(String uuid) {
        this.uuid = uuid;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    @Override
    public String toString() {
        return String.format("id: %s  ----> info: %s", uuid, info);
    }
}

@Entity(tableName = "info")
每个@Entity类代表一个表中的实体。如果希望表与名称不同,可以在通过此处进行修改。
@PrimaryKey
每个实体都需要一个主键。
@NonNull
表示参数,字段或方法返回值永远不能为空。
 @ColumnInfo(name = "uuid")

如果希望表的列与成员字段名称不同,可以通过此注解指定

接下来创建DAO

@Dao
public interface InfoDao {

    @Query("SELECT * FROM info")
    List getInfoList();

    @Query("SELECT * FROM info where uuid = :id")
    InfoEntity getInfoEntity(String id);

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void addInfo(InfoEntity infoEntity);

    @Delete
    void deleteInfo(InfoEntity infoEntity);

    @Update
    int update(InfoEntity infoEntity);

}

在DAO(数据访问对象)中,指定SQL查询并将它们与方法调用相关联。编译器检查SQL并从便捷注释生成查询以查找常见查询.

我们的CRUD操作全部在注解里声明,并且,也会检查你的CRUD语句是否正确。

接下来就是创建Database 了.

@Database(entities = {InfoEntity.class}, version = 1, exportSchema = false)
public abstract class InfoDataBase extends RoomDatabase {

    private static InfoDataBase INSTANCE;

    public static InfoDataBase getInstance(Context context) {
        if (INSTANCE == null) {
            synchronized (InfoDataBase.class) {
                if (INSTANCE == null) {
                    INSTANCE = Room.databaseBuilder(context.getApplicationContext(), InfoDataBase.class, "info.db").build();
                }
            }
        }
        return INSTANCE;
    }

    public abstract InfoDao getInfoDao();
}

1.public abstract class InfoDataBase extends RoomDatabase  {}
  创建一个public abstract类继承自RoomDatabase 
2.@Database(entities = {InfoEntity.class}, version = 1, exportSchema = false)
  将类注释为Room数据库,声明属于数据库的实体并设置版本号。列出实体将在数据库中创建表。exportSchema传 true的话, 把 Scheme 导出到一个文件夹里面,具体的可以直接点进去看注释。
3. public abstract InfoDao getInfoDao();
  定义使用数据库的DAO。为每个@Dao提供抽象的“getter”方法。

到这一步,Room的代码基本完成了。

List infoList = InfoDataBase.getInstance(DbListActivity.this).getInfoDao().getInfoList();

可以用上面这样的代码去调用了。

不过,上面的代码必须放在异步线程去调用,不然会直接崩溃,报错:

java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.

为了方便封装,我们可以写一个Source

public interface InfoSource {

    interface LoadInfoListCallBack {

        void onDataNoAvailable();

        void onLoadSuccess(List list);
    }

    interface GetInfoCallBack {
        void onDataNoAvailable();

        void onLoadSuccess(InfoEntity entity);
    }

    void getInfoList(LoadInfoListCallBack callBack);

    void getInfo(String uuid, GetInfoCallBack callBack);

    void addInfo(InfoEntity entity);

    void deleteInfo(InfoEntity entity);

    void updateInfo(InfoEntity entity);

}

然后用一个用其实现类来进行数据操作,如下:

public class CustomInfoSource implements InfoSource {

    private InfoDao dao;
    private AppExecutor appExecutor;

    public CustomInfoSource(@NonNull InfoDao dao, @NonNull AppExecutor appExecutor) {
        this.dao = dao;
        this.appExecutor = appExecutor;
    }

    @Override
    public void getInfoList(final LoadInfoListCallBack callBack) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                final List infoList = dao.getInfoList();
                appExecutor.getMainThread().execute(new Runnable() {
                    @Override
                    public void run() {
                        if (infoList == null || infoList.size() == 0) {
                            callBack.onDataNoAvailable();
                        } else {
                            callBack.onLoadSuccess(infoList);
                        }
                    }
                });

            }
        };

        appExecutor.getDiskIO().execute(runnable);
    }

    @Override
    public void getInfo(String uuid, GetInfoCallBack callBack) {

    }

    @Override
    public void addInfo(final InfoEntity entity) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                dao.addInfo(entity);
            }
        };

        appExecutor.getDiskIO().execute(runnable);
    }

    @Override
    public void deleteInfo(InfoEntity entity) {

    }

    @Override
    public void updateInfo(InfoEntity entity) {

    }
}

这样的话,我们再进行调用也方便:

source.getInfoList(new InfoSource.LoadInfoListCallBack() {
    @Override
    public void onDataNoAvailable() {
    }

    @Override
    public void onLoadSuccess(List infos) {
        list.addAll(infos);
        adapter.notifyDataSetChanged();
    }
});
关于Room的简单使用也就这样了,附上demo地址https://github.com/mnb65482/SimpleRoomDemo




你可能感兴趣的:(开发笔记)