MVVM数据持久化
之前我们分别介绍了MVVM框架的悲剧,项目搭建以及网络请求,接下来在这篇文章当中,我们来聊一聊MVVM数据持久化的问题,也就是我们常说的缓存
Room
Room持久库提供了一个SQLite抽象层,让你访问数据库更加稳健,提升数据库性能。 简介地址 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复制代码
方便统一管理。 至此 我们就可以设计新的结构图如下:
根据结构图:
- View:Activity/Fragment
- ViewModel:使用RxJava处理数据
- Local Data:Room
- Remote Data:Retrofit
Room的使用
1.创建相应的Entity
Entity当中常用的几个属性
- 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.daoimport android.arch.persistence.room.Entityimport android.arch.persistence.room.PrimaryKey/** * @author yangzc * @data 2018/11/7 10:23 * @desc 创建Post的Entity * */@Entitydata 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.daoimport android.arch.persistence.room.Daoimport android.arch.persistence.room.Insertimport android.arch.persistence.room.OnConflictStrategyimport android.arch.persistence.room.Queryimport io.reactivex.Single/** * @author yangzc * @data 2018/11/5 17:40 * @desc PostDao * */@Daointerface PostDao { @Insert(onConflict = OnConflictStrategy.REPLACE) fun insetAll(postinfo: List) @Insert(onConflict = OnConflictStrategy.REPLACE) fun inserttWeather(postinfo: PostEntity) @Query("SELECT * FROM postentity") fun getWeathInfo(): Single }复制代码
3.创建数据库
相当于创建RetrofitClient对象。
我们需要创建一个AppDatabase,这个类是包含了所以的Entity以及操作他们的DAO。这个类需要继承RoomDatabase的抽象类
package yang.cehome.com.mvvmdemo.model.localimport android.arch.persistence.room.Databaseimport android.arch.persistence.room.Roomimport android.arch.persistence.room.RoomDatabaseimport android.content.Contextimport yang.cehome.com.mvvmdemo.model.local.dao.PostDaoimport 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集成完成