Наблюдайте за данными из комнаты, используя модель View в Котлине - PullRequest
0 голосов
/ 08 сентября 2018

Я создаю приложение для социальных сетей и следую MVVM Pattern Я застрял на observing данных из БД. Насколько я знаю, Dao методы должны выполняться на фоне thread. Но я не могу реализовать viewmodel из Repository Class.I вставит код, Кто-нибудь может мне помочь?

ДАО

@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 голосов
/ 08 сентября 2018

Во-первых, вам не нужно вставлять все Feed объекты один за другим в Database. Внутри FeedDao вы можете создать метод для вставки List<Feed>

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

Чем не нужно вызывать loadFromDB() внутри метода onPostExecute(), потому что ваш метод fun getAllFeed(): LiveData<List<Feed>>() из @FeedDao возвращает LiveData, и вы можете добавлять Observer к нему и каждый раз, когда данные внутри базы данных изменения Observer будут запущены.

А для запросов сети / базы данных вы всегда можете использовать NetworkBoundResource https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample/app/src/main/java/com/android/example/github/repository/NetworkBoundResource.kt

Надеюсь, я как-то помог:)

...