How to cancel coroutine when user making new request?

Viewed 411

When user typing city name in editText it's calling method from viewModel:

override fun onTextChanged(text: CharSequence?, start: Int, before: Int, count: Int) {
                handler.removeCallbacksAndMessages(null)
                if (text?.isNotEmpty() == true) {
                    val searchCity = Runnable {
                        viewModel.getWeatherByCityName(text.toString())
                    }
                    handler.postDelayed(searchCity, DELAY)
                }
            }

this method in viewModel is making viewModelScope and calling network request from repository by city name:

fun getWeatherByCityName(
        cityName: String
    ) {

        viewModelScope.launch {
            weatherRepository.getWeatherByCityName(cityName, localeUnit, localeLang)
                .onEach { dataState ->
                    when (dataState) {
                        is ApiResult.Success -> {
                            prefRepository.setUserInput(cityName)
                            cityId = dataState.data.cityId
                            _screenState.value = dataState
                        }
                        else -> _screenState.value = dataState
                    }
                }
                .launchIn(viewModelScope)
        }
    }

So my question is: when user typing a new city name it's calling new method with new network request but the previous coroutine still operating even the user don't need this answer anymore because he want a new one. How can i immediately cancel this coroutine if user calling a new method/new city name for getting new weather?

1 Answers

You can keep a reference to the job and check if it's not null (meaning that there is an existing request) and cancel it then start a new one

in ViewModel

private val job: Job? = null

and in you function

fun getWeatherByCityName(
        cityName: String
    ) {

        if (job != null) {
            job.cancel()
        }
        job = viewModelScope.launch {
            
        }
    }
Related