Search code examples
androidnetwork-programmingkotlinkotlinx.coroutines

Cancel file upload (retrofit) started from coroutine kotlin android


I'm trying to get rid of RxJava2 in my project and replace it with kotlin coroutines. 90% of my RxJava code is no longer exists but I still can`t replace one network request. User can send photo to backend in my App (multipart form data request using retrofit). User also can cancel photo upload if it was not loaded yet. With RxJava I was able to keep Disposable object of upload request and if it is not disposed yet I could dispose it if user clicked cancel upload button. As result of this action network request was canceled too. So we could save some user traffic and battery. Is it possible to achieve same logic with kotlin coroutines? In official docs written that coroutines cancellation is cooperative and we need some suspending function in loop (or in between file parts send) in order to stop coroutine. So is this the case when RxJava is better choice or did I missed something?


Solution

  • If you are using retrofit for your network calls, you can add their coroutines call adapter from here.

    You cancel a coroutine's running part by cancelling it's job. For example if you are using launch to launch your coroutine, it returns a Job object which can be cancelled.

    val job = launch {
            repeat(1000) { i ->
                println("I'm sleeping $i ...")
                delay(500L)
            }
        }
        delay(1300L) // delay a bit
        println("main: I'm tired of waiting!")
        job.cancel() // cancels the job
        job.join() // waits for job's completion 
        println("main: Now I can quit.")
    

    If you are not using retrofit and using another library, you can retrieve isActive inside you coroutine and cancel the request from your library.

    fun main(args: Array<String>) = runBlocking<Unit> {
        val startTime = System.currentTimeMillis()
        val job = launch {
            var nextPrintTime = startTime
            var i = 0
            while (isActive) { // cancellable computation loop
                // print a message twice a second
                if (System.currentTimeMillis() >= nextPrintTime) {
                    println("I'm sleeping ${i++} ...")
                    nextPrintTime += 500L
                }
            }
        }
        delay(1300L) // delay a bit
        println("main: I'm tired of waiting!")
        job.cancelAndJoin() // cancels the job and waits for its completion
        println("main: Now I can quit.")
    }