1

I want to show ProgressDialog while fetching data from ViewModel and it works fine when I fetch data for the first time, but when I want to refresh the data from API the ProgressDialog starts and does not stops

I create MutableLiveData<Boolean>() and try to manage the visibility but it's not working

This is how i refresh my data from my Activity

private fun loadNorthTram() {
    val model =
        ViewModelProviders.of(this@MainActivity).get(MyViewModelNorth::class.java)

    model.isNorthUpdating.observe(
        this@MainActivity,
        Observer { b ->
            if (b!!)
                AppUtil.showProgressSpinner(this@MainActivity)
            else
                AppUtil.dismissProgressDialog()
        })

    model.getNorthTrams().observe(this@MainActivity, Observer
    {
        if (it != null) {
            setData(it)
        }
    })
}

Below is my ViewModel class

class MyViewModelNorth : ViewModel() {

    private lateinit var mtoken: String
    private val apiService: ApiInterface = ApiClient.client.create(ApiInterface::class.java)
    private lateinit var trams: MutableLiveData<TramModel>
    val isNorthUpdating = MutableLiveData<Boolean>().default(false)

    fun getNorthTrams(): MutableLiveData<TramModel> {
        isNorthUpdating.value = true
        if (!::trams.isInitialized) {
            trams = MutableLiveData()
            callTokenAPI()
        }
        return trams
    }

    private fun callTokenAPI() {
        val tokenObservable: Observable<TokenModel> = apiService.fetchToken()
        tokenObservable
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .doOnNext { self ->
                mtoken = self.responseObject[0].DeviceToken
                callTramAPI()
            }
            .subscribe(getTokenObserver())
    }

    private fun callTramAPI() {
        val apiService: ApiInterface = ApiClient.client.create(ApiInterface::class.java)
        val observable: Observable<TramModel> = apiService.fetchTrams(AppUtil.NORTH_TRAMS, mtoken)
        observable
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(getTramObserver())
    }

    private fun getTokenObserver(): Observer<TokenModel> {
        return object : Observer<TokenModel> {
            override fun onComplete() {}
            override fun onSubscribe(d: Disposable) {}

            override fun onNext(tokenModel: TokenModel) {}

            override fun onError(e: Throwable) {
                if (e is HttpException) {
                    val errorBody = e.response().errorBody()
                    HttpErrorUtil(e.code()).handelError()
                }
            }
        }
    }

    private fun getTramObserver(): Observer<TramModel> {
        return object : Observer<TramModel> {
            override fun onComplete() {
                isNorthUpdating.value = false
            }

            override fun onSubscribe(d: Disposable) {}

            override fun onNext(t: TramModel) {
                if (!t.hasError && t.hasResponse)
                    trams.value = t
                else if (t.errorMessage.isBlank())
                    applicationContext().showToast(t.errorMessage)
                else
                    applicationContext().showToast(applicationContext().getString(R.string.something_wrong))
            }

            override fun onError(e: Throwable) {

                if (e is HttpException) {
                    val errorBody = e.response().errorBody()
                    HttpErrorUtil(e.code()).handelError()
                }
            }
        }
    }

    public fun getIsNothUpdating(): LiveData<Boolean> {
        return isNorthUpdating
    }

    fun <T : Any?> MutableLiveData<T>.default(initialValue: T) = apply { setValue(initialValue) }
}
user1506104
  • 6,554
  • 4
  • 71
  • 89
Akshay Katariya
  • 338
  • 4
  • 16
  • Are you calling `getNorthTrams()` multiple times? It's gonna work for the first time because `callTokenAPI()` will be called, but next time you call the it `trams` is probably already initialized so it won't execute inside of the if statement. – Sanlok Lee Feb 03 '19 at 08:33

1 Answers1

0

I have not tested your code but I think your problem is in function getNorthTrams() in viewmodel.

First time when you fetch data, trams is not initialized, your api call is happening and at only onCompleted, you are setting isNorthUpdating.value = false. This code works.

But when you refresh data, trams is already initialized. So, there is no case for isNorthUpdating.value = false, which is causing progress dialog to not dismiss.

So I think you should handle else case in your viewmodel.

    fun getNorthTrams(): MutableLiveData<TramModel> {
    isNorthUpdating.value = true
    if (!::trams.isInitialized) {
        trams = MutableLiveData()
        callTokenAPI()
    }else{
        //do your thing for refresh
        isNorthUpdating.value = false
    }
    return trams
}

Also, in api call, if error occur, you should set isNorthUpdating to false and show some error message. Otherwise, progress dialog will always be showing even if some error occur in api call.

Xuzan
  • 335
  • 1
  • 11