【问题标题】:MediatorLiveData onChanged not called although it's being observed尽管正在观察 MediatorLiveData onChanged,但未调用它
【发布时间】:2021-03-07 23:09:13
【问题描述】:

在 NetworkBoundResource 文件中,直到 "Log.d(TAG, "init: called")" 行生效,但是 results.addSource 不起作用,尽管我在我的 RestaurantViewModel 类中观察它,并且在我的 Activity 中观察到另一个在 NetworkBoundResource 中观察结果的 MediatorLiveData。

如果我运行应用程序,则不会发生任何事件。没有错误。很明显,缺少某些东西,但是我找不到它是什么。任何答案都会非常有帮助。提前谢谢你。

RestaurantViewModel.kt

class RestaurantViewModel(application: Application): AndroidViewModel(application) {

companion object {
    private const val TAG = "RestaurantViewModel"
}

class Factory(private val application: Application) : ViewModelProvider.Factory {
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        return RestaurantViewModel(application) as T
    }
}

private val mRestaurantRepository: RestaurantRepository = RestaurantRepository.instance(application)
private val results: MediatorLiveData<Resource<RestaurantDetail?>?> = MediatorLiveData()

val restaurantDetail: MediatorLiveData<Resource<RestaurantDetail?>?>
    get() = results

fun searchByRestaurantId(resId: Int) {
    executeSearch(resId)
}

private fun executeSearch(resId: Int) {
    val repositorySource = mRestaurantRepository.searchByRestaurantId(resId)

    results.addSource(repositorySource) { detailResource ->
        if(detailResource != null) {
            Log.d(TAG, "executeSearch: $detailResource")
            results.value = detailResource

            results.removeSource(repositorySource)
        } else {
            results.removeSource(repositorySource)
        }
    }
}

}

RestaurantActivity.kt 中的

subscribeObservers 函数

private fun subscribeObservers() {
    mRestaurantViewModel?.restaurantDetail?.observe(this, Observer { detailResource ->
        if (detailResource != null) {
            when (detailResource.status) {
                Resource.Status.SUCCESS -> {
                    detailResource.data?.let { restaurantDetail ->
                        Log.d(TAG, "subscribeObservers: $restaurantDetail")
                        setRestaurantProperties(restaurantDetail)
                    }
                }
                Resource.Status.ERROR -> {

                }
                Resource.Status.LOADING -> {

                }
            }
        }
    })
}
RestaurantRepository.kt 中的

searchByRestaurantId 函数

fun searchByRestaurantId(resId: Int): LiveData<Resource<RestaurantDetail?>?> {
    return object: NetworkBoundResource<RestaurantDetail, RestaurantResponse>() {
        override fun saveCallResult(item: RestaurantResponse) {
            Log.d(TAG, "saveCallResult: called")
            item.getRestaurant?.let { restaurantDetail ->
                Log.d(TAG, "saveCallResult: $restaurantDetail")
                restaurantDao!!.insertRestaurant(restaurantDetail)
            }
        }

        override fun shouldFetch(data: RestaurantDetail?): Boolean {
            return true
        }

        override fun loadFromDb(): LiveData<RestaurantDetail?> {
            Log.d(TAG, "loadFromDb: called")
            return restaurantDao!!.searchByRestaurantId(resId)
        }

        override fun createCall(): LiveData<ApiResponse<RestaurantResponse?>?> {
            Log.d(TAG, "createCall: called")
            val apiResponse = ServiceGenerator.retrofitService.searchByRestaurantId(resId)
            Log.d(TAG, "createCall: $apiResponse")
            return apiResponse
        }

    }.asLiveData
}

NetworkBoundResource.kt

abstract class NetworkBoundResource<CacheObject, RequestObject> {

companion object {
    private val TAG: String? = "NetworkBoundResource"
}

private var results: MediatorLiveData<Resource<CacheObject?>?> = MediatorLiveData()

init {
    init()
    Log.d(TAG, "NetworkBoundResource: called")
}

fun setValue(newValue: Resource<CacheObject?>?) {
    if (results.value !== newValue) {
        results.value = newValue
    }
}

private fun init() {

    // update LiveData for loading status
    results.value = loading(null)

    // observe LiveData source from local db
    val dbSource: LiveData<CacheObject?> = loadFromDb()
    Log.d(TAG, "init: called")
    results.addSource(dbSource) { cacheObject ->
        results.removeSource(dbSource)
        if (shouldFetch(cacheObject)) {
            // get data from the network
            fetchFromNetwork(dbSource)
        } else {
            results.addSource(
                dbSource
            ) { cacheObject -> setValue(Resource.success(cacheObject)) }
        }
    }
}

【问题讨论】:

    标签: mvvm mediatorlivedata


    【解决方案1】:

    哦,问题解决了。在收到 apiResponse 之前,我从 mediatorLivedata 中删除了源。这就是我无法调用 onChanged 方法的原因。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多