Android架構組件Room介紹與使用

關於Room

Room是Google官方提供的數據庫ORM框架,使用起來非常方便。Room在SQLite上提供了一個抽象層,以便在利用SQLite的全部功能的同時能更加流暢的訪問數據庫。

Room中三個主要組件:

  • Database:該組件用來創建一個database holder。註解定義實體的列表,類的內容定義從數據庫中獲取數據的對象(DAO)。它也是底層連接的主要入口。這個被註解的類是一個繼承RoomDatabase的抽象類。在運行時,可以通過調用Room.databaseBuilder() 或者 Room.inMemoryDatabaseBuilder()來得到它的實例。

  • Entity:該組件的一個示例表示數據庫的一行數據,對於每個Entity類來說,都會有對應的table被創建。想要這些Entity被創建,就需要卸載上面的Database的註解參屬entities列表中,默認Entity中的所有字段都會來創建表,除非該字段上加上@Ignore註解。

  • Dao:該組件用來表述具有Data Access Object(DAO)功能的類或者接口,DAO類時Room的重要組件,負責定義查詢(添加或者刪除等)數據庫的方法。使用@Database註解的類中必須定義一個不帶參數的抽象方法,這個方法返回使用@Dao註解的類,返回類型爲@Dao註解過的類的抽象方法Room會在編譯時生成這個類的實現。

添加Room庫的依賴

首先在Google的Maven存儲庫(項目最外層的build.gradle文件中添加如下:

allprojects {
    repositories {
        jcenter()
        google()
    }
}

然後再app/build.gradle文件中添加相關依賴

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    // Room依賴
    implementation 'android.arch.persistence.room:runtime:1.0.0'
    annotationProcessor "android.arch.persistence.room:compiler:1.0.0"
    ......
}

定義Entity

當一個類用 @Entity 註解並且被 @Database 註解中的 entities 屬性所引用,Room就會在數據庫中爲這個被 @Entity 註解的類創建一張表。

PrimaryKey

每個Entity必須至少有一個主鍵(Primary Key),即使只有一個屬性,也要使用@PrimaryKey來註釋這個屬性。如果想讓Room爲Entity設置自增ID,需要設置@PrimaryKey的autoGenerate屬性。

ColumnInfo

如果想要自定義表中的字段時,需要在屬性上面加上 @ColumnInfo 註解,如:@ColumnInfo(name = “ID”),”ID”爲自定義字段名。

@Entity(tableName = "PHONE")
public class PhoneBean implements Parcelable {

    @PrimaryKey(autoGenerate = true) // 設置主鍵
    @ColumnInfo(name = "ID") // 定義對應的數據庫的字段名成
    private int id;

    @ColumnInfo(name = "PHONE")
    private String phone;

    @ColumnInfo(name = "NAME")
    private String name;

    @ColumnInfo(name = "DATE")
    private Date date;

    public PhoneBean(String phone, String name, Date date) {
        this.phone = phone;
        this.name = name;
        this.date = date;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Date getDate(){
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(this.id);
        dest.writeString(this.phone);
        dest.writeString(this.name);
        dest.writeLong(this.date != null ? this.date.getTime() : -1);
    }

    protected PhoneBean(Parcel in) {
        this.id = in.readInt();
        this.phone = in.readString();
        this.name = in.readString();
        long tmpDate = in.readLong();
        this.date = tmpDate == -1 ? null : new Date(tmpDate);
    }

    public static final Parcelable.Creator<PhoneBean> CREATOR = new Parcelable.Creator<PhoneBean>() {
        @Override
        public PhoneBean createFromParcel(Parcel source) {
            return new PhoneBean(source);
        }

        @Override
        public PhoneBean[] newArray(int size) {
            return new PhoneBean[size];
        }
    };
}

定義轉換

TypeConverter

使用@TypeConverter註解定義轉換的方法,如下,將Date類型的數據轉換成Long類型來存儲。

public class ConversionFactory {

    @TypeConverter
    public static Long fromDateToLong(Date date) {
        return date == null ? null : date.getTime();
    }

    @TypeConverter
    public static Date fromLongToDate(Long value) {
        return value == null ? null : new Date(value);
    }
}

如圖,示例中將Date屬性值轉換爲Long類型存儲到數據庫

Room創建的數據庫表

讀取到數據庫的Date屬性值,再將Date屬性值轉換爲字符串顯示

讀取到的Date字段值

定義Dao

Dao組件定義一系列的增刪改查操作。其中 UpdateDetele 操作是根據定義的主鍵進行。

@Dao
public interface PhoneDao {

    /**
     * 查詢所有
     *
     * @return
     */
    @Query("SELECT * FROM PHONE")
    List<PhoneBean> getPhoneAll();

    /**
     * 根據指定字段查詢
     *
     * @return
     */
    @Query("SELECT * FROM PHONE WHERE phone = :phone")
    List<PhoneBean> loadPhoneByIds(String phone);

    /**
     * 項數據庫添加數據
     *
     * @param phone
     */
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void insertAll(List<PhoneBean> phone);

    /**
     * 修改數據
     *
     * @param phone
     */
    @Update()
    void update(PhoneBean phone);

    /**
     * 刪除數據
     *
     * @param phoneBean
     */
    @Delete()
    void delete(PhoneBean phoneBean);
}

創建數據庫

@Database(entities = {PhoneBean.class}, version = 1, exportSchema = false)
@TypeConverters({ConversionFactory.class})
public abstract class PhoneDatabase extends RoomDatabase {

    public static PhoneDatabase getDefault(Context context) {
        return buildDatabase(context);
    }

    private static PhoneDatabase buildDatabase(Context context) {
        return Room.databaseBuilder(context.getApplicationContext(), PhoneDatabase.class, "PHONE.db")
                .allowMainThreadQueries()
                .build();
    }

    public abstract PhoneDao getPhoneDao();
}

使用

增加
private void insertPhone(String mName, String mPhone) {
    List<PhoneBean> mPhones = new ArrayList<>();
    mPhones.add(new PhoneBean(mPhone, mName));
    PhoneDatabase.getDefault(getApplicationContext()).getPhoneDao().insertAll(mPhones);
}
查詢
private void queryPhone() {
    List<PhoneBean> mPhoneLists = PhoneDatabase.getDefault(getApplicationContext()).getPhoneDao().getPhoneAll();
    // 其他代碼......
}
修改
private void updatePhone(String name, String phone) {
    PhoneDatabase.getDefault(getActivity().getApplicationContext()).getPhoneDao().update(new PhoneBean(phone, name));
    // ......
}
刪除
private void deletePhone() {
    PhoneDatabase.getDefault(getActivity().getApplicationContext()).getPhoneDao().delete(mPhoneBean);
    // ......
}

查看案例源代碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章