I would like my app users to be able to cancel file upload.
My coroutine upload job in ViewModel looks like this
private var uploadImageJob: Job? = null
private val _uploadResult = MutableLiveData<Result<Image>>()
val uploadResult: LiveData<Result<Image>>
get() = _uploadResult
fun uploadImage(filePath: String, listener: ProgressRequestBody.UploadCallbacks) {
//...
uploadImageJob = viewModelScope.launch {
_uploadResult.value = withContext(Dispatchers.IO) {
repository.uploadImage(filePart)
}
}
}
fun cancelImageUpload() {
uploadImageJob?.cancel()
}
Then in the repository the Retrofit 2 request is handled like this
suspend fun uploadImage(file: MultipartBody.Part): Result<Image> {
return try {
val response = webservice.uploadImage(file).awaitResponse()
if (response.isSuccessful) {
Result.Success(response.body()!!)
} else {
Result.Error(response.message(), null)
}
} catch (e: Exception) {
Result.Error(e.message.orEmpty(), e)
}
}
When cancelImageUpload()
it called the job gets cancelled and the exception gets caught in the repository but the result won't get assigned to uploadResult.value
.
Any ideas please how to make this work?
PS: There is a similar question Cancel file upload (retrofit) started from coroutine kotlin android but it suggests using coroutines call adapter
which is depricated now.
Have finally managed to make it work by moving withContext
one level up like this
uploadImageJob = viewModelScope.launch {
withContext(Dispatchers.IO) {
_uploadResult.postValue(repository.uploadImage(filePart))
}
}