kotlin – Android observeable in viewmodel only works once-ThrowExceptions

Exception or error:

I am using android architecture components and following a tutorial from here. This tutorial uses single source of truth strategy with local cashing using room and retrofit. I have implemented this part in my app and it works well. But in one Fragment I am facing the problem. The problem is that i have 4 buttons on activity and by clicking any button the data is filtered based on category say Category A category b etc. When I first load the fragment the data is displayed as expected but when I click on 2nd button to get data for category B the old data is showed and new data is never refreshed.
Here is my code.
In fragment inside oncreateview i have this observer

 private fun getCategory() {
        viewModel.categorys.observe(viewLifecycleOwner, Observer { result ->
            when (result.status) {
                Result.Status.SUCCESS -> {
                    progressDialogue.hideDialog()

                    Log.d("category", "On success")
                    val item = result.data
                    setAdapter(item)
                }
                Result.Status.LOADING -> {
                    progressDialogue.showDialog()
                    Log.d("category", "On loading")
                }
                Result.Status.ERROR -> {
                    Log.d("category", "On Error")
                    progressDialogue.hideDialog()
                    Snackbar.make(binding.root, result.message!!, Snackbar.LENGTH_LONG).show()
                }
            }
        })
    }

this is my view model

class CategoryViewModel @Inject constructor(repository: CateRepository) : ViewModel() {
         var categorys = repository.mCate// ***this value not changes after 1st run***   
   }

this is my repository

class CateRepository @Inject
constructor(
    private val daoCat: DaoCat,
    private val remoteDataSource: RemoteDataSource,
     private val request: String
) {
    val mCate= resultLiveData(
        databaseQuery = {
            daoBundles.getAllCategories(BaseClass.Category)
        },
        networkCall = { remoteDataSource.getBundles(request) },
        saveCallResult = {
            daoCat.deleteAndInsert()
        })

My question is how can i refresh this value on button click
var categorys = repository.mCate//
Update 1

This is my click listener

binding.btnGroup.setOnCheckedChangeListener { _, checkedId ->
            val dao = AppDatabase.getInstance(BaseClass.appContext).bundlesDao()
            when (checkedId) {
                R.id.btnHybrid -> {
                    BundleParams.setBundleType(BundleTypes.Hybrid.type)
                    getSelectedBundles(BundleTypes.Hybrid.type)
                }
                R.id.btnVoice -> {
                    BundleParams.setBundleType(BundleTypes.Voice.type)
                    getSelectedBundles(BundleTypes.Voice.type)
                }
                R.id.btnSMS -> {
                    BundleParams.setBundleType(BundleTypes.SMS.type)
                    getSelectedBundles(BundleTypes.SMS.type)
                }
                R.id.btnData -> {
                    BundleParams.setBundleType(BundleTypes.Data.type)
                    getSelectedBundles(BundleTypes.Data.type)
                }
                R.id.btnFavourites -> {
                    BundleParams.setBundleType(BundleTypes.Favorites.type)
                    getSelectedBundles(BundleTypes.Favorites.type)
                }
            }
        }





private fun getSelectedBundles(mType: String) {
        viewModel.updateCategory()
    }
How to solve:

I can suggest to add method to ViewModel and call it when button is pressed:

class CategoryViewModel @Inject constructor(repository: CateRepository) : ViewModel() {
    val categories: LiveData<Result<PromotionDetails>> = MutableLiveData<Result<PromotionDetails>>()

    // call this method when button is pressed
    fun updateCategory() = viewModelScope.launch(Dispatchers.IO) { // launch a coroutine
        val result = repository.resultLiveData()
        (categories as MutableLiveData).postValue(result) // update result value in main thread
    }
}

class CateRepository @Inject constructor(...) {

    fun resultLiveData(): Result<PromotionDetails> {
        return resultLiveData(
            databaseQuery = { daoBundles.getAllCategories(BaseClass.Category) },
            networkCall = { remoteDataSource.getBundles(request) },
            saveCallResult = { daoCat.deleteAndInsert() }
        )
    }
}

To use viewModelScope in MainViewModel class add dependency to build.gradle file:

final LIFECYCLE_VERSION = “2.2.0-rc03” // add most recent version

api “androidx.lifecycle:lifecycle-viewmodel-ktx:$LIFECYCLE_VERSION”

Leave a Reply

Your email address will not be published. Required fields are marked *