Search code examples
retrofit2kotlin-coroutines

Cancel retrofit request when using it with coroutine flow


I have retrofit interface like below:

@GET("products")
fun getProducts(
    @Query("limit") limit: Int,
    @Query("offset") offset: Int
): Flow<List<Product>>

I'm calling this method like below:

restService
    .getProducts(limit, offset)
    .flowOn(ioContext)
    .catch { /* handle error */ }
    .collect { /* handle result */ }

This code snippet could be called in situations:

  1. When pulled Swipe refresh
  2. When loading the next portion of data. That's why I want to cancel the previous request before making a new one. How I can achieve this?

Solution

  • I think your best option is to run the collection in a coroutine that gets cancelled when the data is not needed anymore. It can be as part of a flow. An example:

    combineTransform(limitFlow, offsetFlow, refreshSignal) {
        emitAll(restService.getProducts(limit, offset))
    }.collect { }
    

    (here refreshSignal would emit whenever a refresh is needed).

    The flow returned by getProducts() will be cancelled each time new values are emitted from the input flows.

    You could as well cancel the collection manually, keeping the job and calling cancel on it.

    val getProductsJob = launch {
        restService
            .getProducts(limit, offset)
            .flowOn(ioContext)
            .catch { /* handle error */ }
            .collect { /* handle result */ }
    }
    

    ... then you can cancel that job whenever you feel like:

    getProductsJob.cancel()