前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MVVM的数据持久化(二)——ROOM的使用

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

作者头像
Demo_Yang
发布2018-12-07 10:01:28
6850
发布2018-12-07 10:01:28
举报
文章被收录于专栏:yang0rangeyang0range

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

MVVM框架的搭建(二)——项目搭建

MVVM框架的搭建(三)——网络请求

MVVM的数据持久化(一)——ROOM的集成

ROOM的使用以及实践

上一篇文章,我们已经介绍了MVVM持久化的意义以及工具ROOM,下面我们介绍一下如何在我们项目当中使用,已达到对数据持久化。

修改Model层

这里我们需要修改一下Model层,添加Repository作为ViewModel层的数据源,在Repository里我们进行数据的处理判断

代码语言:javascript
复制
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作为数据源,这里我们只需要修改

代码语言:javascript
复制
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层当中引用
代码语言:javascript
复制
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的话,在数据存和取数据就比较麻烦,类似如下

代码语言:javascript
复制
{
    "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建库比较麻烦,以前用的方法是,建一个实体

在存的时候使用

代码语言:javascript
复制
     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

取的时候采用

代码语言:javascript
复制
     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

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

https://github.com/yang0range/MVVM

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.11.07 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ROOM的使用以及实践
    • 修改Model层
      • 修改我们的ViewModel层的数据源
        • 在View层当中引用
          • 效果
            • 最后
              • 问题
              • 但是这个方法我终究觉得不是一个理想的解决方案,不知道有没有什么好的建议,我们一起讨论一下。
              • 项目地址
              相关产品与服务
              数据库
              云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档