MediatorLiveData onChanged not called although it's being observed

73 Views Asked by At

In NetworkBoundResource file, until the line "Log.d(TAG, "init: called")" gets worked, but results.addSource not work although I am observing it in my RestaurantViewModel class, and the other MediatorLiveData which observes the results in NetworkBoundResource is being observed in my Activity.

If I run the app, no event happens. no error. It's obvious that something is missing but, I can't find what it is. Any answer would be really helpful. Thanks you in advance.

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)
        }
    }
}

}

subscribeObservers function in RestaurantActivity.kt

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 -> {

                }
            }
        }
    })
}

searchByRestaurantId function in RestaurantRepository.kt

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)) }
        }
    }
}
1

There are 1 best solutions below

0
On

Oh issue resolved. I removed the source from the mediatorLivedata before apiResponse is received. This is why I couldn't get the onChanged method called.