1. 程式人生 > >Android 資料庫-Room

Android 資料庫-Room

前言

最近專案中用得資料庫框架 “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的坑

  1. 例項要給一個空參構造.
  2. 要支援儲存Date型別的資料必須加@DateConvert.
  3. 和Rx一起用的時候需要引用Room的Rx庫.
  4. Rx在查詢完記得dispose,否則每次操作操作資料庫都會收到回掉

暫時就遇到這些坑,之後如果遇到再來補上。大家慎踩…

總結

個人感覺上手還是不錯的,開發上也比較爽,還能練寫原生SQL,有Retrtofit使用經驗的上手更快,只是大專案先別急著上,畢竟才出來,先把坑排一排在用。