为了账号安全,请及时绑定邮箱和手机立即绑定

MVVM的数据持久化(二)——ROOM的使用

标签:
Android 架构

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

但是这个方法我终究觉得不是一个理想的解决方案,不知道有没有什么好的建议,我们一起讨论一下。

点击查看更多内容
1人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消