MVP
MVP

Reputation: 181

Android Kotlin Co-routine Exceptions

I'm trying to use Kotlin co-routines to trigger a network request and handle Exceptions. I've looked at a lot of tutorials on co-routines but I'm really struggling to relate what i know to the problem i have.

The problem

Trying to get an exception to be caught in the View, but no Exception is thrown from the ViewModel so the application crashes.

The Code

My Android app has three layers that relate to this issue. I have the View, ViewModel and a Service layer. In the service layer, request.execute() can throw a UserAuthException.

MyView (View)

private val mViewModel: MyViewModel by viewModels()

private fun getFileId() {
    try {
        mViewModel.requestFileId()
    } catch (e: UserAuthException) {
        Timber.i(e)
    }
}

MyViewModel (ViewModel)

private val apiService = MyApiService()

fun requestFileId() {
    viewModelScope.launch {
        ApiService.requestFileId()
    }
}

MyApiService (Service Layer)

suspend fun requestFileId(): FileId = withContext(Dispatchers.IO) {
    request.execute()
}

Things that i have looked at

I have played around with CoroutineExceptionHandlers, supervisorJobs with no luck, but without the fundamental knowledge of how these things work I'm not really making any progress.

Any help would be appreciated, thanks.

Upvotes: 1

Views: 147

Answers (2)

Marko Topolnik
Marko Topolnik

Reputation: 200138

fun requestFileId() {
    viewModelScope.launch {
        ApiService.requestFileId()
    }
}

This is not a suspendable function. It launches a concurrent coroutine and returns right away. Clearly, calling requestFileId() will never throw an exception.

Launching a coroutine is just like starting another thread, it introduces concurrency to your code. If your current code hopes to stay non-concurrent while observing the results of suspendable functions, you may be looking at significant architectural changes to the application to make it behave correctly under concurrency.

Upvotes: 1

xizzhu
xizzhu

Reputation: 895

In your model, change it to something like this:

fun requestFileId() {
  viewModelScope.launch {
    try {
      ApiService.requestFileId()
    } catch (e: Exception) {
      // inform your view
    }
  }
}

Upvotes: 0

Related Questions