本文涉及Library的版本如下:
- androidx.room:room-runtime:2.1.0-alpha03
- androidx.room:room-compiler:2.1.0-alpha03(註解編譯器)
- androidx.room:room-rxjava2:2.1.0-alpha03
Room的介紹
Room為了SQLite提供了一個抽象層,對Android SQLite進行了封裝 , 更加方便地進行資料庫訪問。
Room主要有3個元件:
- Database: 資料庫的持有者。
- Entity: 代表資料庫一張表
- DAO: 資料訪問物件
Room架構圖如下:
從上圖可以知道,應用層需要定義有哪些表; 定義資料訪問物件; 定義資料庫,比如說資料庫名稱,有哪些些表等。下面結合一些簡單的程式碼例子:
// 定義User表, 用Entity註解來表示這個類是一個資料庫表
@Entity
public class User {
// 使用ColumnInfo註解定義一個欄位名, 不用註解預設去變數名
@ColumnInfo(name = "first_name")
public String firstName;
@PrimaryKey // 主鍵
public int id;
}
複製程式碼
// 定義資料訪問物件的介面
@Dao
public interface UserDao { // 定義成介面
// Query註解定義查詢, 引數是sql語句
@Query("SELECT * FROM user")
List<User> getAll();
// 根據id查詢user, :id這裡意思是引用findById方法裡引數id。是room定義固定寫法:冒號+引數名稱
@Query("SELECT * FROM user WHERE id = :id")
User findById(String id);
//Update註解定義更新User
@Update
void udapte(User user);
//Insert註解定義插入User
@Insert
void insert(User user);
//Delete註解定義刪除User
@Delete
void delete(User user);
}
複製程式碼
//定義AppDatabase類,需要是abstract的,繼承RoomDatabase
//使用Database註解,定義entities類, entities引數是一個class[],version是資料庫的版本號
@Database(entities = {User.class, Favorite.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
public abstract FavoriteDao favoriteDao();
private static final String DB_NAME = "room_demo";
private static volatile AppDatabase sInstance;
//通常定義一個單例持有AppDatabase引用
//DB_NAME是資料庫檔名稱
public static AppDatabase getInstance(Application app){
if(sInstance == null){
synchronized (AppDatabase.class){
if(sInstance == null){
sInstance = Room.databaseBuilder(app,
AppDatabase.class, DB_NAME).build();
}
}
}
return sInstance;
}
}
//運算元據庫增刪查
mAppDatabase = AppDatabase.getInstance(this.getApplication());
mAppDatabase.userDao().delete(user);
mAppDatabase.userDao().insert(user);
mAppDatabase.userDao().getAll();
複製程式碼
資料庫遷移
通過RoomDatabase.Builder.addMigrations()新增Migration去實現。程式碼示例如下:
static final Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(SupportSQLiteDatabase database) {
// database.execSQL("");執行sql語句
}
};
static final Migration MIGRATION_2_3 = new Migration(2, 3) {
@Override
public void migrate(SupportSQLiteDatabase database) {
// database.execSQL("");執行sql語句
}
};
Room.databaseBuilder(app,AppDatabase.class, DB_NAME)
.addMigrations(MIGRATION_1_2, MIGRATION_2_3)
.build();
複製程式碼
支援RxJava、LiveData的擴充套件
在定義Dao介面時,可以直接LiveData和Flowable來作為返回資料型別。
@Dao
public interface UserDao {
@Query("SELECT * FROM user")
LiveData<List<User>> getUsersLiveData();
@Query("SELECT * FROM user")
Flowable<List<User>> getUsersFlowable();
}
//LiveData使用例子
public class RoomActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mRoomModel = ViewModelProviders.of(this).get(RoomModel.class);
mRoomModel.getUsersLiveData().observe(this, new Observer<List<User>>() {
@Override
public void onChanged(List<User> users) {
adapter.setData(users);//更新UI
}
});
}
}
public class RoomModel extends AndroidViewModel {
private final AppDatabase mAppDatabase;
public RoomModel(@NonNull Application application) {
super(application);
mAppDatabase = AppDatabase.getInstance(this.getApplication());
}
public LiveData<List<User>> getUsersLiveData() {
return mAppDatabase.userDao().getUsersLiveData();
}
}
//RxJava使用例子
mAppDatabase.userDao().getUsersFlowable()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<List<User>>() {
@Override
public void accept(List<User> users) throws Exception {
adapter.setData(users);//更新UI
}
});
複製程式碼
對RxJava不熟悉自己去了解, 對 LiveData不瞭解可以我之前的文章LiveData
一些遺留的問題
-
利用註解Database並且繼承RoomDatabase,到底是怎麼生存資料庫
-
資料訪問只需要定義一個DAO介面, Dao介面真正實現是怎樣的,增刪改查是如何實現的
-
是如何擴充套件RxJava和LiveData, 並且如何能監聽Flowable和LiveData資料的變更
參考:*