MVVM的資料持久化(一)——ROOM的整合

朝陽楊大爺發表於2018-11-07

MVVM框架的搭建(一)——背景

MVVM框架的搭建(二)——專案搭建

MVVM框架的搭建(三)——網路請求

MVVM的資料持久化(二)——ROOM的使用

MVVM資料持久化

之前我們分別介紹了MVVM框架的悲劇,專案搭建以及網路請求,接下來在這篇文章當中,我們來聊一聊MVVM資料持久化的問題,也就是我們常說的快取

Room

Room持久庫提供了一個SQLite抽象層,讓你訪問資料庫更加穩健,提升資料庫效能。 簡介地址 developer.android.google.cn/training/da… Room在SQLite上提供了一個抽象層,以便在發揮SQLite能力的同時允許流暢的資料庫訪問,最主要的是它讓SQLiteDatabase的使用變得簡單,大大減少了重複的程式碼,並且把SQL查詢的檢查放在了編譯時。而且還可以和RxJava配合使用的十分契合。

Room有3個主要的元件
Database:

包含資料庫持有者,並充當與應用程式持久化的、關係型的資料的底層連線的主要訪問點。 用@Database註解的類應滿足以下條件: 是一個繼承RoomDatabase的抽象類。 在註釋中包含與資料庫相關聯的實體列表。 包含一個具有0個引數的抽象方法,並返回用@Dao註釋的類。 在執行時,您可以通過呼叫Room.databaseBuilder()或Room.inMemoryDatabaseBuilder()獲取資料庫例項。

Entity:

表示資料庫內的表。

DAO:

包含用於訪問資料庫的方法。

以及這三者之間的關係圖:

三者關係圖

加入依賴

以上簡單的介紹了一下Room 下面我們著重介紹如何在我們的框架當中使用 首先加入依賴

    implementation 'android.arch.persistence.room:runtime:1.1.1'
    implementation 'android.arch.persistence.room:rxjava2:1.1.1'
    kapt 'android.arch.persistence.room:compiler:1.1.1'
複製程式碼

看過之前文章的同學們,可以直接放在config.gradle當中,方便統一管理。

 dependVersion = [
 room_version       : '1.1.1'
 ]
      roomLib = [room_runtime: "android.arch.persistence.room:runtime:$dependVersion.room_version",
               room_rxjave2: "android.arch.persistence.room:rxjava2:$dependVersion.room_version"

    ]
    room = [ room: "android.arch.persistence.room:compiler:$dependVersion.room_version"]
    ]
    
     roomDeps = [roomLib.values()]
     roomDep = [room.values()]
 
複製程式碼

在專案當中引用

    implementation project.ext.roomDeps
    kapt project.ext.roomDep
複製程式碼

方便統一管理。 至此 我們就可以設計新的結構圖如下:

結構圖.png

根據結構圖:

  1. View:Activity/Fragment
  2. ViewModel:使用RxJava處理資料
  3. Local Data:Room
  4. Remote Data:Retrofit

Room的使用

1.建立相應的Entity
Entity當中常用的幾個屬性
  1. Primary key 每個entity必須至少定義一個field作為主鍵(primary key)。即使只有一個field,你也必須用@PrimaryKey註釋這個field。如果你想讓Room為entity設定自增ID,你可以設定@PrimaryKey的autoGenerate屬性。如果你的entity有一個組合主鍵,你可以使用@Entity註解的primaryKeys屬性。

2.tableName Room預設把類名作為資料庫的表名。如果你想用其它的名稱,使用@Entity註解的tableName屬性。

3.ColumnInfo Room預設把field名稱作為資料庫表的column名。如果你想讓column有不一樣的名稱,為field新增@ColumnInfo屬性。

4.Indices 和 unique 為了提高查詢的效率,你可能想為特定的欄位建立索引。要為一個entity新增索引,在@Entity註解中新增indices屬性,列出你想放在索引或者組合索引中的欄位。 有時候,某個欄位或者幾個欄位必須是唯一的。你可以通過把@Index註解的unique屬性設定為true來實現唯一性。

5.Embedded 有時你可能想把一個entity或者一個POJOs作為一個整體看待,即使這個物件包含幾個field。這種情況下,你可以使用@Embedded註解,表示你想把一個物件分解為表的子欄位。然後你就可以像其它獨立欄位那樣查詢這些嵌入的欄位。

回到我們的專案當中,建立屬於我們的Entity:

package yang.cehome.com.mvvmdemo.model.local.dao

import android.arch.persistence.room.Entity
import android.arch.persistence.room.PrimaryKey

/**
 * @author yangzc
 *	@data 2018/11/7 10:23
 *	@desc 建立Post的Entity
 *
 */
@Entity
data class PostEntity(
    val message: String,
    @PrimaryKey
    val nu: String,
    val ischeck: String,
    val condition: String,
    val com: String,
    val status: String,
    val state: String
)


複製程式碼
2.建立Dao

相當於Retrofit中的api介面。

Dao負責運算元據庫的方法,也就是說我們一些運算元據庫的動作都是在這裡完成的。不同的是我們不需要這些都用Dao類當中的註解來定義查詢。

package yang.cehome.com.mvvmdemo.model.local.dao

import android.arch.persistence.room.Dao
import android.arch.persistence.room.Insert
import android.arch.persistence.room.OnConflictStrategy
import android.arch.persistence.room.Query
import io.reactivex.Single

/**
 * @author yangzc
 *	@data 2018/11/5 17:40
 *	@desc PostDao
 *
 */
@Dao
interface PostDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insetAll(postinfo: List<PostEntity>)


    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun inserttWeather(postinfo: PostEntity)

    @Query("SELECT * FROM postentity")
    fun getWeathInfo(): Single<PostEntity>

}
複製程式碼
3.建立資料庫

相當於建立RetrofitClient物件。

我們需要建立一個AppDatabase,這個類是包含了所以的Entity以及操作他們的DAO。這個類需要繼承RoomDatabase的抽象類

package yang.cehome.com.mvvmdemo.model.local

import android.arch.persistence.room.Database
import android.arch.persistence.room.Room
import android.arch.persistence.room.RoomDatabase
import android.content.Context
import yang.cehome.com.mvvmdemo.model.local.dao.PostDao
import yang.cehome.com.mvvmdemo.model.local.dao.PostEntity

/**
 * @author yangzc
 *	@data 2018/11/5 18:21
 *	@desc 包含所有Entity以及操作它們的 DAO
 *
 */
@Database(entities = arrayOf(PostEntity::class), version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun WeatherDao(): PostDao

    companion object {
        @Volatile
        private var INSTANCE: AppDatabase? = null

        fun getInstance(context: Context): AppDatabase =
                INSTANCE ?: synchronized(this) {
                    INSTANCE ?: buildDatabase(context).also { INSTANCE = it }
                }

        private fun buildDatabase(context: Context) =
                Room.databaseBuilder(context.applicationContext,
                        AppDatabase::class.java, "app.db")
                        .build()
    }
}

複製程式碼

Ok 至此Room整合完成

專案地址

github.com/yang0range/…

相關文章