I'm working on a codebase with both Java and Kotlin code, i introduced Kotlin coroutines to help in running background tasks, however i have a function in my repository marked with the keyword suspend and i call it from an Intent Service that is written in java to sync local db with remote. However i can only call a suspend function from another suspend function or a coroutine builder. I three options in mind:
Option 1
Use GlobalScope.launch(Dispatchers.IO) on the function so that i can call it from the Intent Service. However GloablScope is not highly recommended in the android context.
Option 2
Make my repository extend Coroutine Scope, create a public function called onCleared that cancels job, then call this function when the service onDestroyed method is called or when the view model onCleared method is called. This option is to try and cancel any running operations.
Option 3
Use the viewmodel scope to launch the coroutine in the repository, then call the viewmodel from the service, however the viewmodel should only be limited to an activity or fragment.
Option 4
Refactor the intent service to Kotlin and use coroutines
4️⃣ 4
m
marstran
02/03/2020, 1:34 PM
You could write a non-suspending wrapper function in Kotlin that runs the function in the appropriate scope. That function would be easier to call from Java.
If you need to return a result, then the wrapper function could take a callback-parameter.
l
louiscad
02/03/2020, 1:48 PM
IntentService is deprecated. You can use WorkManager (CoroutineWorker) instead, or just run it while the user is using your app at the foreground.
☝️ 2
b
bdawg.io
02/03/2020, 6:02 PM
Option 6
Have a wrapper Kotlin function that returns a CompletableFuture using the
future { ... }
builder
g
gildor
02/04/2020, 12:50 AM
future is not somehow better than GlobalScope, it's essentially the same, just exposed as CompletableFuture instead of Job/Deffered
👍 1
Tho I agree with Louis that IntentService is not the best solution (I regret every time when decided to use it) and with others who voted for option 4, but I would be careful with advise to rewrite it to own coroutine based solution or use WorkingManager, IntentService has very strict sequential semantics and lifecycle of service, also if if it Bindable or foreground it makes it even more different
But it really depends what you want to achieve.
If you just need fast working solution, I see no problem just use GlobalScope in your case, just do not do anything in launch after repository method call to avoid leak.
Also, IntentService is a background service that runs on working thread, there is nothing bad to call runBlocking inside, this is how intent service intended to use, block until task is done and only after that it will start processing next intent.
Option 2 will work, but you cannot anymore use this repository from suspend functions properly and await for result, it will essentially background task, which is what I would try to avoid
So I would rewrite only if you know what exactly you want to achieve, not to solve this particular case