一、前言
Room是一個持久層庫,它可以使我們更加方便的操作SQLite數據庫。下面我們介紹它的具體使用。
二、Room的使用介紹
1、創建User實體
package com.jilian.androidarchitecture.common;
import android.arch.persistence.room.ColumnInfo;
import android.arch.persistence.room.Embedded;
import android.arch.persistence.room.Entity;
import android.arch.persistence.room.Ignore;
import android.arch.persistence.room.PrimaryKey;
/**
* 實體類
*/
@Entity(tableName = "user")
public class UserDto {
//主鍵 自增長
@PrimaryKey(autoGenerate = true)
//表名
@ColumnInfo(name = "id")
private Long id;
@ColumnInfo(name = "sex")
private String sex;
@ColumnInfo(name = "username")
private String username;
@ColumnInfo(name = "password")
private String password;
// 指示 Room 需要忽略的字段或方法
@Ignore
private String age;
//把 info內嵌到 UserDto中
@Embedded
private UserInfo info;
public UserInfo getInfo() {
return info;
}
public void setInfo(UserInfo info) {
this.info = info;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String toString() {
return "UserDto{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
下面介紹實體中的註解含義:
@Entity(tableName = "user") 指數據表名爲 user
@PrimaryKey(autoGenerate = true) 設置主鍵,autoGenerate = true 指主鍵自增長
@ColumnInfo(name = "sex") 列名
@Ignore 需要忽略的字段或方法
@Embedded 把其他實體嵌入到該實體,也就是說,該數據表將擁有其他數據表的屬性
2、創建操作數據庫的DAO
package com.jilian.androidarchitecture.dao;
import android.arch.lifecycle.LiveData;
import android.arch.persistence.room.Dao;
import android.arch.persistence.room.Delete;
import android.arch.persistence.room.Insert;
import android.arch.persistence.room.Query;
import android.arch.persistence.room.Update;
import com.jilian.androidarchitecture.common.UserDto;
import java.util.List;
import io.reactivex.Flowable;
/**
* 操作數據庫的dao層 接口
*/
@Dao
public interface UserDao {
/**
* 查詢用戶列表
* @return
*/
@Query("select * from user")
List<UserDto> findUserList();
/**
* 添加用戶
* @param userDtos 可變參數 可以多個
*/
@Insert
void addUser(UserDto...userDtos);
/**
* 根據ID查詢用戶
* @param ids 可以多個ID 查詢多個用戶
*/
@Query("select * from user where id in (:ids)")
List<UserDto> findUserById(Long[] ids);
/**
* 更加用戶名查詢
* @param username
* @return
*/
@Query("select * from user where username = (:username)")
List<UserDto> findUserByName(String username);
/**
* 刪除用戶
* @param userDtos
*/
@Delete
void deleteUser(UserDto...userDtos);
/**
* 更新用戶
* @param userDtos
*/
@Update
void updateUser(UserDto...userDtos);
/**
* 結合 LiveData使用
* @return
*/
@Query("select * from user")
LiveData<List<UserDto>> findUserListForLiveData();
/**
* 結合RxJava使用
* @return
*/
@Query("select * from user")
Flowable<List<UserDto>> findUserListFoRxJava();
}
在DAO層我們定義了常規的增刪改查的方法,同時我們可以配合LiveData和RxJava一起使用。
3、初始化數據庫
package com.jilian.androidarchitecture.db;
import android.arch.persistence.room.Database;
import android.arch.persistence.room.Room;
import android.arch.persistence.room.RoomDatabase;
import android.content.Context;
import com.jilian.androidarchitecture.common.UserDto;
import com.jilian.androidarchitecture.common.UserInfo;
import com.jilian.androidarchitecture.dao.UserDao;
/**
* 創建數據庫
*/
@Database(entities = {UserDto.class,UserInfo.class},version = 1)
public abstract class AppDataBase extends RoomDatabase {
private static AppDataBase appDataBase;
//對外提供需要操作數據庫的DAO
public abstract UserDao getUserDao();
/**
* 以單實例的形式初始化數據 並對外提供 AppDataBase實例
* @param context
* @return
*/
public static AppDataBase getInstance(Context context){
if(appDataBase==null){
synchronized (AppDataBase.class){
if(appDataBase==null){
//"user" 爲數據庫名
appDataBase = Room.databaseBuilder(context.getApplicationContext(),AppDataBase.class,"user_data").build();
}
}
}
return appDataBase;
}
}
初始化數據庫需要創建抽象類並繼承RoomDatabase,我們使用Database 註解,並指定相應的實體創建數據表,和數據庫版本 version。並在抽象類中創建獲取DAO的方法 。
//對外提供需要操作數據庫的DAO
public abstract UserDao getUserDao();
然後我們通過單實例的方式初始化數據庫,並對外提供RoomDatabase實例。
/**
* 以單實例的形式初始化數據 並對外提供 AppDataBase實例
* @param context
* @return
*/
public static AppDataBase getInstance(Context context){
if(appDataBase==null){
synchronized (AppDataBase.class){
if(appDataBase==null){
//"user" 爲數據庫名
appDataBase = Room.databaseBuilder(context.getApplicationContext(),AppDataBase.class,"user_data").build();
}
}
}
return appDataBase;
}
我們通過RoomDatabase實例可以拿到DAO對象,接着通過DAO對象即可對數據表進行操作。
下面我們通過例子來介紹:
三、實例
創建RoomActivity,分別對數據庫進行增刪改查的操作
package com.jilian.androidarchitecture;
import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.Observer;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import com.jilian.androidarchitecture.common.UserDto;
import com.jilian.androidarchitecture.db.AppDataBase;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import java.util.List;
import io.reactivex.Flowable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
public class RoomActivity extends AppCompatActivity {
private static final String TAG = "RoomActivity";
private TextView add;
private TextView update;
private TextView delete;
private TextView query;
private TextView queryList;
private TextView queryLiveData;
private TextView queryRxJava;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_room);
add = (TextView) findViewById(R.id.add);
update = (TextView) findViewById(R.id.update);
delete = (TextView) findViewById(R.id.delete);
query = (TextView) findViewById(R.id.query);
queryList = (TextView) findViewById(R.id.queryList);
queryLiveData = (TextView) findViewById(R.id.queryLiveData);
queryRxJava = (TextView) findViewById(R.id.queryRxJava);
add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread() {
@Override
public void run() {
super.run();
UserDto userDto = new UserDto();
userDto.setUsername("daxiaa");
userDto.setPassword("123456");
AppDataBase.getInstance(RoomActivity.this).getUserDao().addUser(userDto);
}
}.start();
}
});
update.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread() {
@Override
public void run() {
super.run();
UserDto userDto = new UserDto();
userDto.setUsername("zaizai");
userDto.setId(1l);
userDto.setPassword("111111");
AppDataBase.getInstance(RoomActivity.this).getUserDao().updateUser(userDto);
}
}.start();
}
});
delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread() {
@Override
public void run() {
super.run();
UserDto userDto = new UserDto();
userDto.setId(1l);
AppDataBase.getInstance(RoomActivity.this).getUserDao().deleteUser(userDto);
}
}.start();
}
});
query.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread() {
@Override
public void run() {
super.run();
List<UserDto> list = AppDataBase.getInstance(RoomActivity.this).getUserDao().findUserByName("zaizai");
for (int i = 0; i < list.size(); i++) {
Log.e(TAG, "user:" + list.get(i).toString());
;
}
}
}.start();
}
});
queryList.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread() {
@Override
public void run() {
super.run();
List<UserDto> list = AppDataBase.getInstance(RoomActivity.this).getUserDao().findUserList();
for (int i = 0; i < list.size(); i++) {
Log.e(TAG, "user:" + list.get(i).toString());
;
}
}
}.start();
}
});
queryLiveData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread() {
@Override
public void run() {
super.run();
LiveData<List<UserDto>> userListForLiveData = AppDataBase.getInstance(RoomActivity.this).getUserDao().findUserListForLiveData();
userListForLiveData.observe(RoomActivity.this, new Observer<List<UserDto>>() {
@Override
public void onChanged(@Nullable List<UserDto> list) {
if (list != null) {
for (int i = 0; i < list.size(); i++) {
Log.e(TAG, "user:" + list.get(i).toString());
}
}
}
});
}
}.start();
}
});
queryRxJava.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Flowable<List<UserDto>> list = AppDataBase.getInstance(RoomActivity.this).getUserDao().findUserListFoRxJava();
//IO 線程獲取數據
list.subscribeOn(Schedulers.io())
//線程切換
.observeOn(AndroidSchedulers.mainThread()).
subscribe(new Subscriber<List<UserDto>>() {
@Override
public void onSubscribe(Subscription s) {
// 觀察者接收事件 = 1個
s.request(1);
}
@Override
public void onNext(List<UserDto> list) {
for (int i = 0; i < list.size(); i++) {
Log.e(TAG, "user:" + list.get(i).toString());
}
}
@Override
public void onError(Throwable t) {
}
@Override
public void onComplete() {
}
});
}
});
}
}
四、注意
需要注意的是,對SQLite的操作是一個耗時的操作,我們需要在子線程中執行,否則將會拋異常。