Search code examples
androidrx-javarx-androidandroid-livedataobservers

ViewModel observe is running multiple times for a single hit to API


I have a Chart in fragment and a switch. On switch selection the API needs to be hit again with a new value and chart needs to be updated, the API code is as shown:

   private fun hitSecondChartApi(country: String, category: String, market: String, weightKpi: String) {

        userModel.getResponseShareSecondChartData(country, category, market, weightKpi)
        Log.e(TAG, "Inside hitsecondchartapi: "+ country+":"+category+":"+market+":"+weightKpi)
        userModel.responseSecondChartData.observe(this,
                Observer {
                    Log.e(TAG, "Second chart data: " + it.toString())
                    Utils.debugger("FRAG ", "$it")
                    secondChartData = it!!
                    if (it.size > 0) {
                        splitSecondParentList(it!!)
                    } else
                        Utils.showLongToast(requireActivity(), "No Data for Distribution")
//                    userModel.responseSecondChartData.removeObservers(this)
                })
    }

Now the problem here is the "Observer is running multiple times when i turn ON/OFF switch and it is also providing me the values of the previous API request first and then of the current API" E.g The response which i had received in the Switch On state is still again received when i will turn off the switch and vice versa. Its like a stack.

E.g: Switch Turned On: Response off-> Response off-> Response On-> Response On-> Response On

Switch Turned Off: Response On-> Response On-> Response off-> Response off-> Response off

For a workaround i tried to remove the observer which you can also see in the above code in the commented line but it has one flaw because it will only run once and i may or maynot get the current API response from it.

One thing i can do is to filter out the response but i need a proper fix for this issue that i should receive only the current API response at it should run only one time as i won't be able to filter out for the other API's.

So please help me to resolve this problem.


Solution

  • Every time hitSecondChartApi() is called, a new observer is attached to LiveData and these duplicated observers are causing the unexpected result. Solutions like SingleEvent or SingleLiveData can technically hide this effect but it will not remove the root cause.

    Correct solution is to call responseSecondChartData only once at the beginning of the Fragment/Activity initialization. For example:

    fun onActivityCreated(...) {
        userModel.responseSecondChartData.observe(this,
                Observer {
                    Log.e(TAG, "Second chart data: " + it.toString())
                    Utils.debugger("FRAG ", "$it")
                    secondChartData = it!!
                    if (it.size > 0) {
                        splitSecondParentList(it!!)
                    } else
                        Utils.showLongToast(requireActivity(), "No Data for Distribution")
                })
    }
    
    private fun hitSecondChartApi(country: String, category: String, market: String, weightKpi: String) {
        userModel.getResponseShareSecondChartData(country, category, market, weightKpi)
    }
    

    There is no need to remove observer in above code because its creating only one observer.