前言: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") ListgetInfoList(); @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(); }
到这一步,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(Listlist); } 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 ListinfoList = 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关于Room的简单使用也就这样了,附上demo地址https://github.com/mnb65482/SimpleRoomDemoinfos) { list.addAll(infos); adapter.notifyDataSetChanged(); } });