MVVM框架的搭建(一)——背景
MVVM框架的搭建(二)——项目搭建
MVVM框架的搭建(三)——网络请求
MVVM的数据持久化(一)——ROOM的集成
ROOM的使用以及实践
上一篇文章,我们已经介绍了MVVM持久化的意义以及工具ROOM,下面我们介绍一下如何在我们项目当中使用,已达到对数据持久化。
修改Model层
这里我们需要修改一下Model层,添加Repository作为ViewModel层的数据源,在Repository里我们进行数据的处理判断
package yang.cehome.com.mvvmdemo.model.repository
import yang.cehome.com.mvvmdemo.model.local.dao.PostDao
import yang.cehome.com.mvvmdemo.model.remote.PostService
/**
* @author yangzc
* @data 2018/11/6 11:55
* @desc PostRepo
*
*/
class PostRepo constructor(private val remote: PostService, private val local: PostDao){
//首先查看本地数据库是否有数据
fun getPostInfo() = local.getPostInfo()
.onErrorResumeNext {
//本地数据库不存在,会抛出会抛出EmptyResultSetException
//转而进行获取网络数据,成功后保存在数据库
remote.getPostInfo().doOnSuccess { local.inserttPost(it) }
}
}
我们可以看到现在的项目结构为:
项目结构修改我们的ViewModel层的数据源
以前我们都是以PostService作为数据源,现在我们要以PostRepo作为数据源,这里我们只需要修改
package yang.cehome.com.mvvmdemo.viewmodel
import android.databinding.ObservableField
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import yang.cehome.com.mvvmdemo.model.local.dao.PostEntity
import yang.cehome.com.mvvmdemo.model.repository.PostRepo
/**
* @author yangzc
* @data 2018/11/7 10:26
* @desc PostViewModel
*
*/
class PostViewModel(private val repo: PostRepo) {
/******data******/
val postinfo = ObservableField<String>()
/******binding******/
fun loadpost() {
repo.getPostInfo()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ t: PostEntity? ->
postinfo.set(t?.let { it.toString() })
}, { t: Throwable? ->
postinfo.set(t?.message ?: "error")
})
}
}
在View层当中引用
package yang.cehome.com.mvvmdemo.view
import android.databinding.DataBindingUtil
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import com.facebook.stetho.okhttp3.StethoInterceptor
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import yang.cehome.com.mvvmdemo.R
import yang.cehome.com.mvvmdemo.databinding.ActivityMainBinding
import yang.cehome.com.mvvmdemo.model.data.Onclick
import yang.cehome.com.mvvmdemo.model.local.AppDatabase
import yang.cehome.com.mvvmdemo.model.remote.PostService
import yang.cehome.com.mvvmdemo.model.repository.PostRepo
import yang.cehome.com.mvvmdemo.viewmodel.OnclikViewModel
import yang.cehome.com.mvvmdemo.viewmodel.PostViewModel
/**
* MVVM 当中的一个V层 将三者联系起来
*/
class MainActivity : AppCompatActivity() {
private lateinit var mBinding: ActivityMainBinding
private lateinit var mViewMode: OnclikViewModel
private lateinit var mViewMode2: PostViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
/////model
val onclick = Onclick("me", 0)
///ViewModel
mViewMode = OnclikViewModel(onclick)
///binding
val client = OkHttpClient.Builder()
.addNetworkInterceptor(StethoInterceptor())
.build()
val remote = Retrofit.Builder()
.baseUrl("http://www.kuaidi100.com")
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build().create(PostService::class.java)
val local= AppDatabase.getInstance(applicationContext).PostDao()
val repo = PostRepo(remote, local)
////ViewModel2
mViewMode2 = PostViewModel(repo)
mBinding.vm = mViewMode
////binding
mBinding.post = mViewMode2
}
}
效果
根据上面的内容 我们最后看看效果如何
持久化数据效果
根据Stetho我们也可以看到我们本地的数据库
利用Stetho查看本地数据
若想了解Stetho请看这篇文章
安卓调试神器-Stetho的使用
最后
至此关于MVVM的数据持久化的工作,我们就完成了。
但是就目前的方法来说,每次都需要写的模板化的代码太多了,那么我们有没有什么办法简化呢,答案必然是有的。
后面的文章我们会持续介绍到,希望大家持续关注。
问题
我们可以看到,对于ROOM的存储包括之前用的GreenDao这种类似的存储都有一个问题,就是根据数据库对应的格式一个键里面有对应相应的值,那么当我们的Json返回数据当中包含JsonArray的话,在数据存和取数据就比较麻烦,类似如下
{
"com": "zhongtong",
"condition": "F00",
"data": [
{
"context": "【宁波市】 快件到达 【宁波中转部】",
"ftime": "2018-10-11 20:41:45",
"location": "宁波中转部",
"time": "2018-10-11 20:41:45"
},
{
"context": "【宁波市】 快件离开 【宁波】 发往 【宁波中转部】",
"ftime": "2018-10-11 18:23:24",
"location": "宁波",
"time": "2018-10-11 18:23:24"
},
{
"context": "【宁波市】 【宁波】(0574-88014756、0574-88016531、0574-88014575) 的 宁海电商产业园区 (15990572220) 已揽收",
"ftime": "2018-10-11 17:14:34",
"location": "宁波",
"time": "2018-10-11 17:14:34"
}
],
"ischeck": "1",
"message": "ok",
"nu": "7510054353700",
"state": "3",
"status": "200"
}
我们直接生成实体,在用Room建库比较麻烦,以前用的方法是,建一个实体
在存的时候使用
public static String boxing(List<T> List) {
if (List == null || List.size() == 0) {
return "";
} else {
StringBuffer buffer = new StringBuffer();
for (int index = 0; index < payloadList.size(); ++index) {
T t = List.get(index);
Parcel p = Parcel.obtain();
p.writeValue(t);
byte[] bytes = p.marshall();
buffer.append(Base64.encodeToString(bytes, Base64.DEFAULT));
if (index < List.size() - 1) {
buffer.append(SPLIT_CHAR);
}
p.recycle();
}
return buffer.toString();
}
}
这样一个JsonArry就存成了一个String
取的时候采用
public static List<T> unBoxing(String listString) {
List<T> list = new ArrayList<>();
if (!TextUtils.isEmpty(listString)) {
String[] array = listString.split(SPLIT_CHAR);
for (String str : array) {
Parcel p = Parcel.obtain();
byte[] ba = Base64.decode(str, Base64.DEFAULT);
p.unmarshall(ba, 0, ba.length);
p.setDataPosition(0);
list.add((T) p.readValue(T.class.getClassLoader()));
p.recycle();
}
}
return list;
}
这样取得时候String又变成了List
网友评论