how to set coroutine context to Deferred? I use Ja...
# coroutines
a
how to set coroutine context to Deferred? I use Jack Wharton's retrofit2-kotlin-coroutines-adapter for Retrofit and wonder how to make all requests being executed within my custom coroutine context.
v
Use
withContext(myContext) { ... }
To your question - a
Deferred
doesn't have a context AFAIK, only the coroutine that produced the deferred result does
a
As I understand Deferred is like wrapper above coroutine and accepts coroutine context via "async"
And I see only default behavior in retrofit adapter and don't know how to customize it
v
Deferred doesn’t wrap coroutine in case of
retrofit2-kotlin-coroutines-adapter
, it wraps
Call<T>
. Deferred returned from retrofit is not launched via
async
, see https://github.com/JakeWharton/retrofit2-kotlin-coroutines-adapter/blob/master/src/main/java/com/jakewharton/retrofit2/adapter/kotlin/coroutines/experimental/CoroutineCallAdapterFactory.kt#L113
a
What do I need to do in order to make network request within my coroutine context?
z
Pass in whatever construct OkHttp requires in it's builder to specify threading, and build a co-routine dispatcher based on that
l
@adjorno Do you want to set the coroutine context to support cancellation?
g
Or use coroutine adapter for RxJava or Call actually those have the same behavior as Deferred adapter in terms of threading for Retrofit
a
@loeschg I need to set coroutine context for retrofit network requests to have a control on threading
@gildor The whole intention of using coroutines is to drop Rx.
g
@adjorno strange reason to use coroutines :) To control threading of retrofit use custom OkHttp dispatcher
Deferred adapter do not use any additional threading policy and uses default okhttp dispatcher and thread pool
With wrapping to own context you can just set maximum amount of parallel coroutines, it's additional threading policy, not replacement for Retrofit one
And you cannot actually execute request in your context dispatcher (with async API), only start request from your context and get result in your context. Deferred adapter uses async API of Retrofit which implemented under the hood using own thread pool
If you really want to actually execute request in own dispatcher you can use sync API of Retrofit wrapped to coroutine with custom coroutine dispatcher but I don't see why do you need this, coroutines work well with async APIs and to control threading better to use okhttp client API for custom dispatchers
a
The problem is I am not the owner of okhttpclient, third-party library creates it and only synchronous calls are supported. So I can't set a dispatcher to okhttpclient. That is why I am looking for a way to set coroutine context.
g
only synchronous calls are supported
what do you mean? this library doesn’t expose to you okhttp API? What do you actually have now as public API that you can use and what is your problem?
a
It uses okhttpclient for own purposes internally and by the documentation I can't change it's settings
Also I am not able to reach end-point via own created client. So my hands are tied a bit that is why I am trying to control threading on a level so high.
g
I don’t think that coroutines could somehow help you in this situation. Maybe only reflections and hack their library settings
but they still provide you some sort of API as I understand, how does it look?
a
Thanks for the help. I have decided to drop the idea with Deferred and use synchronous request Call<*> within my background coroutine context.
g
@adjorno I don't understand your decision. I don't see any difference between Call and Deferred in your case. It's exactly the same in terms of threading. Both, Call and Deferred request will be run on OkHttp internal dispatcher, completely no difference there. If you use some Call coroutine adapter wrapped to your custom coroutine dispatcher you actually do not control threading of Retrofit, you just use different thread for process result of a request
The only way for you to have own threading for okhttp request, especially if you want to use coroutines for that, is use blocking sync API of okhttp or write custom Deferred adapter that runs
async
coroutine builder with blocking request using your own coroutine dispatcher
l
@gildor You can use
execute()
on
Call<T>
, and in this case, use the coroutineContext you want, although this doesn't allow you to support cancellation
g
@louiscad this is exactly what I meant: use blocking API and wrap it to coroutine but I really not sure that this is good solution