使用Kotlin中的View模型从Room观察数据

时间:2018-09-08 08:39:53

标签: android viewmodel android-room android-livedata android-jetpack

我正在创建一个社交媒体应用,并且遵循MVVM模式 我被DB的observing数据困住了。据我所知,Dao方法必须在后台thread上执行。但是我无法从viewmodel类实现Repository。我将粘贴代码,有人可以给我一些帮助吗?

Dao

@Dao
interface FeedDao{

//Post feed item
@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insert(feed:Feed):Long

//Update feed item
@Update(onConflict = OnConflictStrategy.IGNORE)
fun update(feed: Feed):Int

//Get feed from user friend's
@Query("SELECT * from feed")
fun getAllFeed():LiveData<List<Feed>>
}

存储库

class FeedRepository private constructor(private val feedDao: FeedDao) {

companion object {
    @Volatile private var instance:FeedRepository? = null
    private val apiClient = ApiClient.getApiClient().create(UserClient::class.java)
    fun getInstance(feedDao: FeedDao)= instance?: synchronized(this){
      instance ?: FeedRepository(feedDao).also { instance=it }
     }
}


private fun getFeedResponse() {

    //TODO:Check to change parameter values after adding Paging Functionality
    val call: Call<List<Feed>> = apiClient.getFeed(20, 0)
    call.enqueue(object :Callback<List<Feed>>{
        override fun onFailure(call: Call<List<Feed>>?, t: Throwable?) {
            Log.e("FeedRepository","Feed Callback Failure")
            Timber.d(t?.message)
        }

        override fun onResponse(call: Call<List<Feed>>?, response: Response<List<Feed>>?) {
            if(response!!.isSuccessful){
                Timber.i("Successful Response -> Adding to DB")
                addResponseTODB(response.body()!!)
            }else{
                when(response.code()){
                    400 -> Timber.d("Not Found 400")
                    500 -> Timber.d("Not logged in or Server broken")
                }

            }

        }
    })
}

private fun addResponseTODB(items:List<Feed>){
    Timber.d("Response --> DB Started")
    object :  AsyncTask<List<Feed>,Void,Boolean>(){
        override fun doInBackground(vararg params: List<Feed>?): Boolean {
            var needsUpdate:Boolean = false
            for(item in params[0]!!.iterator()){
                var inserted = feedDao.insert(item)
                if(inserted.equals(-1)){
                    var updated = feedDao.update(item)
                    if(updated > 0){
                        needsUpdate = true
                    }
                }else{
                    needsUpdate = true
                }
            }
            return needsUpdate
        }

        override fun onPostExecute(result: Boolean?) {
            if (result!!){
                loadFromDB()
            }
        }

    }.execute(items)
}


private fun loadFromDB(){
    Timber.d("loadFromDB")

    object :AsyncTask<Void,Void,LiveData<List<Feed>>>(){
        override fun doInBackground(vararg params: Void?): LiveData<List<Feed>>? {
            return feedDao.getAllFeed()
        }

        override fun onPostExecute(result: LiveData<List<Feed>>?) {

        }
    }.execute()
}


public fun fetchFeed(){
    Timber.d("fetchFeed")
    loadFromDB()
    getFeedResponse()
}

}

ViewModel

class FeedViewModel private constructor(private val 
feedDao:FeedDao):ViewModel(){
// TODO: Implement the ViewModel

private val feedRepository= FeedRepository.getInstance(feedDao)
public val feed = MediatorLiveData<List<Feed>>()
val value = MutableLiveData<Int>()
init {
        feed.addSource(feed,feed::setValue)
}

companion object {
    private const val NO_FEED = -1
}

fun getFeedLD() = feed

}

1 个答案:

答案 0 :(得分:0)

首先,您不需要在Feed中一个接一个地插入所有Database个对象。您可以在FeedDao内创建一个方法来插入List<Feed>

@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insert(feed: List<Feed>):Long

然后,不必在loadFromDB()方法内调用onPostExecute(),因为您从fun getAllFeed(): LiveData<List<Feed>>()来的@FeedDao方法会返回LiveData,并且您可以添加{ {1}},并且每次数据库中的数据更改时,Observer都会被触发。

对于网络/数据库请求,您始终可以使用Observer https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample/app/src/main/java/com/android/example/github/repository/NetworkBoundResource.kt

希望我有所帮助:)