Search code examples
androidkotlinkotlin-extensionrx-kotlin

Kotlin, how can retry request if get error when tap on button of dialog


Let imagine situation on Kotlin, when we try get request but hasn't internet connection and we get error, then show AlertDialog, and we need retry request if user click on "positive button".

This method check for exist user by phone number:

override fun checkPhone(phone: String, context: Context) {
    view?.let {
        it.showOrHideProgressBar(true)
        apiManager.checkPhone(phone)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe({ result ->
                    view?.showOrHideProgressBar(false)
                    if (result.user_exists) {
                        view?.showLogin()
                    } else {
                        val code = result.confirmation_code
                        confirmPhone(phone, code, context)
                    }
                }, { error ->
                    handleAnyError(error, context)
                }).addToCompositeDisposable(compositeDisposable)
    }
}

And here common method for handle errors:

private fun handleAnyError(it: Throwable, context: Context) {
    view?.showOrHideProgressBar(false)
    when (it) {
        is SocketTimeoutException -> showDialogWithException(context)
        is UnknownHostException -> showDialogWithException(context)
        else -> {
            if (it.message.equals(MESS_429)) {
                view?.showAnyError(context.getString(R.string.err_429))
            } else if (it.message.equals(MESS_422)) {
                view?.showAnyError(context.getString(R.string.err_422))
            }
        }
    }
}

Finally, method to show dialog suggesting retrying request when click positive button:

fun showDialogWithException(context: Context) {
if (!(context as Activity).isFinishing) {
    DialogInternetUtils().showOkDialog(
            context,
            context.getString(R.string.no_internet_connection),
            DialogInterface.OnClickListener
            { dialogInterface, i ->
                dialogInterface?.dismiss()
                if (i == Dialog.BUTTON_NEGATIVE) {
                    dialogInterface!!.dismiss()
                    return@OnClickListener
                } else if (i == Dialog.BUTTON_POSITIVE) {
                    // here handle click button positive, need retry request
                }
            })
}

}

Please, help me finish handle click on positive button to retry request. I guess, need handle error in methods .doOnError() or .onErrorResumeNext() but I'm stuck here...


Solution

  • You could pass a function to be executed when the dialog button is clicked:

    fun showDialogWithException(context: Context, action: () -> Unit) {
      if (!(context as Activity).isFinishing) {
        DialogInternetUtils().showOkDialog(
            context,
            context.getString(R.string.no_internet_connection),
            DialogInterface.OnClickListener
            { dialogInterface, i ->
              dialogInterface?.dismiss()
              if (i == Dialog.BUTTON_NEGATIVE) {
                dialogInterface!!.dismiss()
                return@OnClickListener
              } else if (i == Dialog.BUTTON_POSITIVE) {
                action()
              }
            })
      }
    }
    
    private fun handleAnyError(it: Throwable, context: Context, action: () -> Unit) {
      view?.showOrHideProgressBar(false)
      when (it) {
        is SocketTimeoutException -> showDialogWithException(context, action)
        is UnknownHostException -> showDialogWithException(context, action)
        else -> {
          if (it.message.equals(MESS_429)) {
            view?.showAnyError(context.getString(R.string.err_429))
          } else if (it.message.equals(MESS_422)) {
            view?.showAnyError(context.getString(R.string.err_422))
          }
        }
      }
    }
    
    override fun checkPhone(phone: String, context: Context) {
      view?.let {
        it.showOrHideProgressBar(true)
        apiManager.checkPhone(phone)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io())
            .subscribe({ result ->
              view?.showOrHideProgressBar(false)
              if (result.user_exists) {
                view?.showLogin()
              } else {
                val code = result.confirmation_code
                confirmPhone(phone, code, context)
              }
            }, { error ->
              handleAnyError(error, context, { checkPhone(phone, context) })
            }).addToCompositeDisposable(compositeDisposable)
      }
    }