Concurrency in kotlin coroutine flow - android

I am new to this kotlin coroutine flow, am wondering that how could i achieve the concurrency inside the flow, Whereas according to the documentation it says launch,scope and withContext cannot be used inside the flow. without this How would i able to achieve the concurrency in kotlin flow
Can anyone help me with this?

You're probably looking for the channelFlow builder. You can start a coroutine inside of it and emit the result once it's done. Its documentation states...
Creates an instance of the cold Flow with elements that are sent to a
SendChannel provided to the builder’s block of code via ProducerScope.
It allows elements to be produced by code that is running in a
different context or concurrently.
You can check its official documentation and its usage here.

Related

CoroutineScope(SupervisorJob()) vs Global Scope

What is the difference between these two?
I was following a tutorial, and the teacher said we need a scope that lives as long as the app lives, created the scope manually with SupervisorJob. Doesn't GlobalScope do the same thing?
I researched about this, but couldn't find a proper explanation. Thanks.
The difference between these two specific examples is that GlobalScope cannot be cancelled, but the other one can. When you call cancel() on a CoroutineScope created with the CoroutineScope() constructor function, all of its children coroutines get canceled.
GlobalScope will throw an IllegalStateException if you try to cancel() it, because it has no Job to be a parent of coroutines that it launches.
When you call CoroutineScope() without passing it a Job, it gets a generic Job automatically to be the parent of its coroutines. A generic parent Job like this will cancel all of its children coroutines if any of them fail. If you explicitly use SupervisorJob(), then if any of its children fail, they won't cause all their siblings to be canceled. This is a behavior that is similar to GlobalScope, since GlobalScope coroutines have no siblings that they could cause to be cancelled through a shared parent.
The reason GlobalScope is discouraged is that it has no supervisory capabilities. It should only be used for coroutines that should run for the entire lifetime of an app session. But if you're doing important work that should not be cancelled on Android, coroutines are not a good choice anyway because they aren't handling the cases where your app is in the background. In those cases you should be using a service or WorkManager instead. So, the actual legitimate use cases for GlobalScope, or any CoroutineScope that is never cancelled, are extremely rare.
I think the reason they added #DelicateCoroutinesApi is that so many people were misusing GlobalScope. (Probably because they unfortunately used it in the beginner documentation on how to use coroutines.) It is not correct to get around the warning by using CoroutineScope(SupervisorJob()) or CoroutineScope(Dispatchers.IO), etc. instead of GlobalScope, because all that does is mask the warning without changing the behavior other than creating a redundant CoroutineScope. If you have a legitimate use for GlobalScope, you should use #OptIn(DelicateCoroutinesApi::class) to dismiss the warning.

Is Task<T>.await() main-safe?

I'm writing my first Kotlin app and am using firebase services for auth, db & storage. As it is not possible to make an atomic Firestore + Storage operation, I find myself in quit a callback-hell for a simple image upload (with error fallbacks and all). Thus - I decided to refactor my app to use coroutines. I found some examples (like here and here) but I noticed that the repository-level functions in those examples are not wrapped with withContext(Dispatchers.IO){ } like shown in android docs. Should they? I guess this is two questions in one:
Should Firebase operations always be called with the IO dispatcher?
Is kotlinx-coroutines-play-services's Task<T>.await() main-safe?
And a bonus question: I wrap all my Firebase calls in a proxy object for decoupling - is there a way to set all functions of an object (/class) to run with the same context, or do I have to wrap each function with withContext(Dispatchers.IO){ } separately?
Thanks a lot!
Should Firebase operations always be called with the IO dispatcher?
All Firebase APIs are asynchronous and designed to be called safely from the main thread unless otherwise stated in the API documentation.
Is kotlinx-coroutines-play-services's Task.await() main-safe?
Yes. As the API documentation states (emphasis mine):
Awaits for completion of the task without blocking a thread.
It's a suspend fun, and they do not block. However, they do not really make sense to call outside of a coroutine.

Which one is better approach while performing multiple background tasks Kotlin Coroutines or ThreadPool?

I'm trying to implement start syncing process while app comes foreground.
I want to make multiple API call in the background thread, Which one will be better approach for this scenario Kotlin Coroutines or ThreadPool executor
I have tried with Kotlin Coroutines, but it seems like it try to execute all functions call in parallel which cause some Lag in APP initial times. is there a best approach to execute multiple functions in parallel
of course, Kotlin Coroutines, because coroutines aren't necessarily bound to any particular thread. A coroutine can start executing in one thread, suspend execution, and resume on a different thread. Coroutines aren't managed by the operating system. They're managed at the user space level by the Kotlin Runtime.
Kotlin Co-routines are the way to go.
Why? :
They are cheap.
Increases code readability.
Configuration setup is less (as compared to RxJava) for simple tasks.
try this
viewModelScope.launch{
val function1Async=async{ function1()}
val function2Async=async{function2()
function1Async.await()
function2Async.await()
}
If the alternative is to use ThreadPools, then you should use coroutines. They are built to make this easier. Also, you would save some memory since you would be sharing threads with other processes.
If what you need is a single thread that's continuously running in the background. Then maybe a thread is the way to go to ensure it's execution is not interrupted by a pending coroutine. Although an isolated single threaded dispatcher should solve this problem (if you have it).
You mentioned experiencing lag? Was this lag averted when you used a threadpool? If this is an issue, then fire the coroutines from another coroutine. :)

What are the Kotlin Coroutines, How they are different from live data

I am starting to work with new things that are developed by the developer community Android, one of them is Coroutines. I have used the LiveData
and I assumed while using them, they are also lifecycle safe, then why coroutines are introduced and how they are different from LiveData. I have seen the video on Coroutines at Youtube, from developer channel, but I don't understand that completely. How Suspend and Resume works better than LiveData.
Ok first of all coroutines don't really relate too much with LiveData although they might share here and there some concepts.
Coroutines are used to perform async operation: Retreive data from network, database etc.
Coroutines can be used as "LiveData" if you are talking in the context of Channels or Flows (which I don't recomend because you will lose the lifecycle in it). With coroutines you can switch to threads easily.
Suspend functions are just functions that hold and don't run directly. Any suspending function should be inside a coroutine.
The simplest use case I can give you is this:
runBlocking{
//you are inside of a coroutine
val data = getDataFromBackground()
}
suspend fun getDataFromBackground(): SomeDataType = receiveSomeData()
The receiveSomeData method is also marked with suspend keyword.
But of course there is a lot more. The documentation is perfect way to start.
I also have a personal article about coroutines, you may find them easy there.
There is only one point I can think of that you can replace data with coroutines, and that's using Channels. The view won't be observing for LiveData but will be consuming values comming from a channel, created and shared with DI or something.
EDIT:
If you really want to use LiveData + coroutines please check this awesome library by the Android team.
Coroutines is for asynchronous job. Live Data are used to update your View (Activity & Fragment)

How to properly approach threading with Room

I am confused about Room and can not find an answer in the documentation.
So, the library enforces using queries on a separate Thread, which is understandable. However, it seems that Delete queries are not included in this limitation and can be freely called from the UI Thread. They also always return a raw output value, without a chance to wrap it in an Observable.
What is the correct way to use the delete call in Room then? Should it be run on a separate Thread? If not, what about performance and concurrent modifications?
If you use LiveData to retrieve data from Room, it's executed in worker thread. For, other queries you can use Executors and Repository pattern. You can check out this page for guide to app architecture.
You can check out this link for Rx and other architecture component samples.
Analysis note by the question author:
In the sample they use a Completable to wrap the Room delete call and then schedule it onto the io() scheduler, reacting to the empty complete and any errors. That specific code can be found here.

Categories

Resources