azizbekian
azizbekian

Reputation: 62189

Coroutines: run a Deferred on a specific CoroutineContext

I'm giving a try to Kotlin Coroutines inside an Android app, specifically I've imported Kotlin Coroutine Adapter for Retrofit.

Kotlin Coroutine Adapter changes Retrofit interface to return a Deferred<T> instead of Call<T>.

What I don't understand is how to launch this Deferred in a particular CoroutineContext that I want to. Consider following code:


    class MyViewModel @Inject constructor(
        private val foo: Foo,
        @Named("ui") private val uiContext: CoroutineContext,
        @Named("network") private val networkContext: CoroutineContext
    ) : ViewModel() {

      fun performSomeJob(param: String) {
          launch(uiContext) {
            try {
              val response = foo.bar(param).await()
              myTextView.setText(response.name)
            } catch (error: Throwable) {
              Log.e(error)
            }
          }
    }

Where foo.bar(param) returns Deferred<SomeModel>.

This code works, but I'm not sure on what CoroutineContext this foo.bar(param) is being executed (CommonPool??).

How to explicitly specify, that I want foo.bar(param) to be executed in a networkContext?


    val response = async(networkContext) { foo.bar(param) }.await()

This code doesn't work, because response is evaluated to Deferred<SomeModel> instead of SomeModel (which I want to achieve).

Upvotes: 1

Views: 664

Answers (1)

Marko Topolnik
Marko Topolnik

Reputation: 200168

The foo.bar() call doesn't start another coroutine, it just wraps the native Retrofit Call so that its state changes get propagated to Deferred. Retrofit manages its own threads to perform its operations and this works just as it would without the coroutine wrapper. If you have a specific concern, you can manage it by configuring Retrofit in the usual way.

The only thing that should matter to you is that your coroutine is executing in the UI context.

Upvotes: 1

Related Questions