How can we use `Coroutines with <http://Dispatcher...
# coroutines
r
How can we use `Coroutines with Dispatchers.IO`inside Android Service instead of
HandlerThread + Looper
? I tried and it worked for limited use case but not sure about generic use case. I feel it is not a good practice and will not work for all cases? Is it?
g
What do you exactly mean? What is your problem
Use Dispatchers.IO is fine on any context
r
In
Service
usually, we create our own worker thread + looper to execute long running tasks. What about using coroutines instead of our usual approach?
@gildor 👆 Is it a good approach?
g
I think it’s good to use coroutines for this You will have much better code, no pool, no looper
r
Yes, I tried and it worked but wondering what would happen if I start that service again? In usual approach new thread is not created again. Will play with the coroutine way and will post back here.
g
If you use
<http://Dispatchers.IO|Dispatchers.IO>
threads will be reused
you can use own dispathcher, just do not create it in a thread, otherwise you have to recreate all of them
in general it depends on what you do in your service. If it’s blocking IO use IO, if it’s CPU consuming operation use own dispatcher or Dispatchers.Default.
r
👍
g
If it’s just some async non-blocking code, you don’t need any particular dispatcher, use Dispatchers.Main or Dispatchers.Default, anyway it will not blocking
r
Hi @gildor Here is my working solution for
Service
,
IntentService
using
Coroutines
. https://gist.github.com/RohitSurwase/6a31ecdbcdc7e8712a6b517e305d7308 I would really appreciate if you could have a look at it and let me know your thoughts. Though I have fewer doubts about it, I would ask it later. Thanks!
g
You should use runBlocking for Service, this will block Main thread
But it’s fine for IntentService
r
runBlocking would work if we are doing really small work but that is not always the case, usually I have seen some projects making API calls using service and it creates own handler_looper for that service. So this should work even for those case.
May I ask my doubts?
g
Sure
I don’t understand why you need runBlocking, just use buffered channel of infinity capacity and use
offer
to add job
r
1. I could not get CoroutineName in the logs. 2. Is it ok to create own ActorMessage data class to pass data, any better way? 3. I could figure out how to use onCompletionListener of Actors. 4. Is this way of using Actors safe as there will something called ComplexActors?
g
it creates own handler_looper for that service
Yes, but you don’t need this with coroutines, because they provide own abstraction for cross-thread communication
r
I don’t understand why you need runBlocking, just use buffered channel of infinity capacity and use
offer
to add job
Ok, I will have a look into it.
g
1. Did you enabled debug mode of coroutines? 2. It’s fine and it’s boilerplate, yes. Will be solved by typed actors https://github.com/Kotlin/kotlinx.coroutines/pull/485 3. onCompletionListener? 4. see 2
runBlocking would work if we are doing really small work
Big issue in this case, that send potentially can suspend forever, not in your case because you have Channel.UNLIMITED, but what if handlerActor implementation will change
r
3. there is a parameter
onCompletion: CompletionHandler?
for Actors
g
You shouldn’t use it. use
channel.invokeOnCompletion
instead. What is your actual problem?
r
Just wanted to call
job.cancel() and stopSelf()
on actor completion.
g
this should work
produce{}.invokeOnCompletion { stopSelf() }
also you can simplify scope initialization:
override val coroutineContext: CoroutineContext = <http://Dispatchers.IO|Dispatchers.IO> + Job()
r
Yes I did.
g
probably you should add
invokeOnCompletion
not to channel, but to your scope Job
r
it creates own handler_looper for that service
Yes, but you don’t need this with coroutines, because they provide own abstraction for cross-thread communication
Does this mean even if we use only
Dispatchers.Main
our blocking code will not block main thread? If yes then on which thread our blocking code executes?
g
It will block, of course, wrap blocking code to IO dispatcher
Android Handler is just an API to send messages from one thread to another
coroutines can do this as well
r
I used
runBlocking
in
onStartCommand
as
handlerActor.send(msg)
is not allowed without
Coroutines
.
g
use
offer
to add job
r
Sure, I had skipped to look into channels as doc say it is still experimental. Now, will have a look into it. Thanks.
g
All channels and actors (which is just wrapper for channels) stuff is experimental
r
May I know a short intro of yours? You are really so much supportive. Thanks!
g
Hah? %) Glad to help
r
I mean since when you are working with Kotlin? Are you a member of Kotlin team?
g
I’m of course use Kotlin for work, but nope, I’m not a JB employee %)
r
Okay