一、前言
- 在项目中很多很多的页面用了很多的枚举,而产品和需求发对完发完版本这个枚举更改过很多次。或者前端与后端更改没有通知我们移动端,导致出现移动端前端不一样的展示的问题,所以决定枚举有后端返回 key,value的形式我们自己去匹配查找value展示。这样避免了我们因为这个问题而发版。
- 虽然说目前服务返回了只有几种类型的枚举(例如:公司类型大约有15个左右,单据类型有10多个,发票类型有10个左右......)但是以后肯定还会继续添加,还有可能会把目前项目使用的枚举进行迁移。所以考虑到存储到本地避免多次请求。
二、 为啥要使用Room
-
目前项目中使用的时MVP模式开发,如果以后改为MVVM对于数据请求页面缓存优化更友好(Room返回livedata使用viewmodel观察数据变化进行更新)。
-
在网上搜索了一下Greedao与Room对比插入和查询,Room更占优势
三、基本使用
- 导入依赖
roomRuntime = "androidx.room:room-runtime:$room_version",
roomCompiler = "androidx.room:room-compiler:$room_version",
// RxJava support for Room
roomRxjava2 = "android.arch.persistence.room:rxjava2:$room_version",
roomKapt = "androidx.room:room-compiler:2.2.5"
- 插件
apply plugin: 'kotlin-kapt'
- 创建表
@Entity
data class EnumData(
@PrimaryKey
var id: Long = 0,
var costApplicationTypes: HashMap<String, String>? = null,
var noCostApplicationTypes: HashMap<String, String>? = null,
var zongbuInvoiceTitles: HashMap<String, String>? = null,
var firmTypes: HashMap<String, String>? = null
)
-
注解
@Entity
需要在创建的表@PrimaryKey
键 (@PrimaryKey(autoGenerate = true)
设置键自增)@TypeConverters(TypeConverter::class)
(TypeConverter
需要自己创建并写两个方法使用@TypeConverter
标注例:
class MapTypeConverter {
@TypeConverter
fun stringToMap(value: String): HashMap<String, String> {
return Gson().fromJson(value, object : TypeToken<HashMap<String, String>>() {}.type)
}
@TypeConverter
fun mapToString(value: HashMap<String, String>?): String {
return if (value == null) "" else Gson().toJson(value)
}
}
上面是map的转换,也就是说如果你想要往数据库中写入Map数据需要MapTypeConverter
和在其上使用@TypeConverters
- 创建 AppDatabase
@Database(entities = [EnumData::class], version = 4, exportSchema = false)
@TypeConverters(MapTypeConverter::class)
abstract class AppDatabase : RoomDatabase() {
abstract fun enumDataDao(): EnumDataDao
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, "admin.db"
)
//数据结构发生改变不加fallbackToDestructiveMigration()会引起APP崩溃。作用:更新版本之后清空数据库
.fallbackToDestructiveMigration()
//可在主线程操作
.allowMainThreadQueries()
.build()
}
}
@TypeConverters(MapTypeConverter::class)
如还有List的数据需要添加list的Converter
- 创建EnumDataDao
/**
*
* @Description Room 数据库 增删改查方法
* @date 2020/9/15 4:13 PM
* @author BryceCui
* @Version 1.0
*
* 1、Completable:只有onComplete和onError方法,即只有“完成”和“错误”两种状态,不会返回具体的结果。
* 2、Single:其回调为onSuccess和onError,查询成功会在onSuccess中返回结果,需要注意的是,如果未查询到结果,即查询结果为空,会直接走onError回调,抛出EmptyResultSetException异常。
* 3、Maybe:其回调为onSuccess,onError,onComplete,查询成功,如果有数据,会先回调onSuccess再回调onComplete,如果没有数据,则会直接回调onComplete。
* 4、Flowable/Observable:这是返回一个可观察的对象,查询的部分有变化时,都会回调它的onNext方法,没有数据变化的话,不回调。直到Rx流断开。
*/
@Dao
interface EnumDataDao {
@Transaction
@Query("SELECT * FROM enumdata ORDER BY id DESC LIMIT 1")
fun getAllEnumData():Maybe<EnumData?>
/**
* OnConflictStrategy.REPLACE:冲突策略是取代旧数据同时继续事务
* OnConflictStrategy.ROLLBACK:冲突策略是回滚事务
* OnConflictStrategy.ABORT:冲突策略是终止事务
* OnConflictStrategy.FAIL:冲突策略是事务失败
* OnConflictStrategy.IGNORE:冲突策略是忽略冲突
*/
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertEnumData(data: EnumData)
}
- 插入使用
/**
* 插入枚举到数据库
*/
fun insertEnumOnRoom(response: EnumData): Disposable? {
return Single.fromCallable {
AppDatabase.getInstance(AdminApplication.instance!!).enumDataDao().insertEnumData(response)
}.subscribeOn(Schedulers.io()).observeOn(Schedulers.io()).doOnError {
Log.e("doOnError", "doOnError")
}.doOnSuccess {
Log.e("doOnSuccess", "doOnSuccess")
}.subscribe()
}
- 查询使用
/**
* 从数据库获取所有枚举
*/
fun getAllEnumOnRoom() {
AppDatabase.getInstance(AdminApplication.instance!!).enumDataDao().getAllEnumData().subscribeOn(Schedulers.io()).observeOn(Schedulers.io())
.doOnSuccess {
AdminApplication.instance!!.enumData = it
Log.e("doOnNext", it.toString())
}
.doOnError {
Log.e("getAllEnum", it.toString())
}.doOnComplete {
Log.e("getAllEnum", "doOnComplete")
}.subscribe()
}
四、数据库升级需要注意
- 升级需要自己写升级的SQL语句(都有哪些改动)
- 自行百度
五、总结
-
增删改查需要自己写SQL语句有点......
-
对非基础类型存储不是很友好需要自己写
TypeConverters
而写好像一个List<T>
一种T
需要一个。这个目前没有找到写一种的方法。 -
最后 写的不好 不喜勿喷哈!!! 但接受纠正。
网友评论