前言: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<InfoEntity> 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
[email protected](entities = {InfoEntity.class}, version = 1, exportSchema = false)
将類注釋為Room資料庫,聲明屬于資料庫的實體并設定版本号。列出實體将在資料庫中建立表。exportSchema傳 true的話, 把 Scheme 導出到一個檔案夾裡面,具體的可以直接點進去看注釋。
3. public abstract InfoDao getInfoDao();
定義使用資料庫的DAO。為每個@Dao提供抽象的“getter”方法。
到這一步,Room的代碼基本完成了。
List<InfoEntity> 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<InfoEntity> 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<InfoEntity> 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<InfoEntity> infos) {
list.addAll(infos);
adapter.notifyDataSetChanged();
}
});
關于Room的簡單使用也就這樣了,附上demo位址https://github.com/mnb65482/SimpleRoomDemo