Android 資料庫-Room
阿新 • • 發佈:2018-11-17
前言
最近專案中用得資料庫框架 “ActivieAndroi” 由於作者停止維護了,它在升級到8.0之後會發生Crash,因此,我們準備給專案換一個數據庫。主要考慮了Relam,Room,GreendDao 三個開源得資料庫框架。
內容
Room
Google 支援的ARCH框架推薦;使用原生SQL;註解
使用
網上一半教程都是在翻譯官方文件,有興趣的可以自己去看下官方給的Document & Demo
Git:https://github.com/googlesamples/android-architecture-components/
Document: https://developer.android.com/training/data-storage/room/
1 引用Room庫
dependencies {
def room_version = "1.1.0" // or, for latest rc, use "1.1.1-rc1"
implementation "android.arch.persistence.room:runtime:$room_version"
annotationProcessor "android.arch.persistence.room:compiler:$room_version"
// optional - RxJava support for Room
implementation "android.arch.persistence.room:rxjava2:$room_version"
// optional - Guava support for Room, including Optional and ListenableFuture
implementation "android.arch.persistence.room:guava:$room_version"
// Test helpers
testImplementation "android.arch.persistence.room:testing:$room_version "
}
2 定義資料表實體類
@Entity(tableName = "user_tb")
public class UserRoom {
@PrimaryKey(autoGenerate = true)
private int uid;
@ColumnInfo
private String name;
@ColumnInfo
private int age;
@ColumnInfo
private Date birthday;
... 省略了get/set
}
3 編寫Dao
直接看Code吧,因為是ORM資料庫,註解當然少不了。是不是有點想Retrofit得寫法?而且支援寫原生SQL,我覺得是很Nice得!別特麼說Android程式設計師不需要學SQL,沒點底子出了問題你都不曉得咋搞的。
@Dao
public interface UserDao {
@Insert
Long insertUser(UserRoom user);
@Query("SELECT * FROM user_tb")
Flowable<List<UserRoom>> queryAll();
@Query("SELECT * FROM user_tb")
List<UserRoom> queryForAll();
@Query("SELECT * FROM user_tb WHERE name = :name")
int deleteByName(String name);
@Query("SELECT * FROM user_tb WHERE datetime(birthday/1000, 'unixepoch') >= datetime('now','-1 hour') ")
Flowable<List<UserRoom>> queryWithinHour();
@Delete
void deleteUser(UserRoom user);
@Query("DELETE FORM user_tb where uid = :id")
void deleteUserById(int id)
}
4 在NApplication中初始化
寫一個類繼承RoomDatabaes,我是寫了一個單利.
// 要生成的資料表例項類
@Database(entities = {UserRoom.class},version = 1,exportSchema = false)
// 如果要儲存Date資料,需要加這個來轉換
@TypeConverters({DateConverts.class})
public abstract class AndroidDataBases extends RoomDatabase {
public abstract UserDao userDao();
private static volatile AndroidDataBases INSTANCE;
public static AndroidDataBases crateDatabases(Context context) {
if (INSTANCE == null) {
synchronized (AndroidDataBases.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
AndroidDataBases.class, "room.db")
.build();
}
}
}
return INSTANCE;
}
public static AndroidDataBases getInstance(){
return INSTANCE;
}
}
public class DateConverts {
@TypeConverter
public static Date revertDate(Long value) {
return value == null ? null : new Date(value);
}
@TypeConverter
public static Long converterDate(Date date) {
return date == null ? null : date.getTime();
}
}
CURD
有一點需要注意得是Room預設是必須在子執行緒操作得,否則拋異常。
// 先獲取一個UserDao
var userDao: UserDao = AndroidDataBases.getInstance().userDao()().userDao();
// 插入一條資料
val user: UserRoom = UserRoom("admin2", 25, Date(System.currentTimeMillis()))
AsyncTask.execute({
var raw = userDao.insertUser(user)
Log.d("picher","操作行號:"+raw)
})
// 查詢資料
AsyncTask.execute(Runnable {
var raws = userDao.queryForAll()
Log.d("picher","資料庫:"+raws.size)
})
// 刪除資料 & 修改資料類似 只要在Dao中寫好了直接調
看下用了Rx得寫法(有坑,插入資料時也會觸發這個回掉):
首先需要引用Room 自己的RX庫。
// RxJava support for Room
compile "android.arch.persistence.room:rxjava2:1.1.1-rc1"
private fun flowableDemo() {
userDao.queryAll().subscribeOn(Schedulers.io())
.map({ users ->
var names = ""
for (item in users) names += item.name
names
}).observeOn(AndroidSchedulers.mainThread()).subscribe({ names -> showTv.text =names})
}
Room的坑
- 例項要給一個空參構造.
- 要支援儲存Date型別的資料必須加@DateConvert.
- 和Rx一起用的時候需要引用Room的Rx庫.
- Rx在查詢完記得dispose,否則每次操作操作資料庫都會收到回掉
暫時就遇到這些坑,之後如果遇到再來補上。大家慎踩…
總結
個人感覺上手還是不錯的,開發上也比較爽,還能練寫原生SQL,有Retrtofit使用經驗的上手更快,只是大專案先別急著上,畢竟才出來,先把坑排一排在用。