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

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.

Related

Concurrency in kotlin coroutine flow

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.

How does a Coroutine Continuation internally work?

I have been working with coroutines for few weeks and sometimes its tough to understand the real working difference between thread concurrency and coroutine concurrency.
How suspend functions works internally ? How is continuation block helping in resuming the computation after suspension.
How is sequential computation of the line of code inside coroutine not blocking the thread ? and how is it better than thread concurrency ?
How suspend functions works internally?
Briefly, on the Java platform a suspend fun compiles into bytecode that is dramatically different from a plain function. It receives a hidden extra parameter (the continuation), creates its own continuation object, and the entire body of the function is implemented (approximately) as a big switch statement that allows the function to jump into the middle of the body when resuming.
When a suspend fun suspends, the underlying Java method actually returns. The return value is a special COROUTINE_SUSPENDED singleton object which the framework knows how to interpret. It is the responsibility of the suspend fun itself to save the continuation object where it will be accessible when the result of the function is ready.
The official documentation has a good in-depth description of these details.
How is continuation block helping in resuming the computation after suspension.
This is related to what I said above, that the suspend fun itself is responsible for ensuring it gets resumed later on. It must do that inside the block provided by the function suspendCoroutineOrReturn. User code doesn't call it directly, but the more high-level analogs suspendCoroutine and suspendCancellableCoroutine. These take over the concern of resuming the coroutine on the appropriate thread and the developer is responsible only for ensuring that continuation.resume() is called with the result when it becomes available. This typically happens in a callback you pass to an async call.
You can study this answer that tries to explain the suspend-resume mechanism in a self-contained example.
How is sequential computation of the line of code inside coroutine not blocking the thread?
Because it actually compiles into returning from the function and later on resuming by jumping into the middle of the function body.
and how is it better than thread concurrency?
Native threads are heavyweight resources that take time to create and destroy. Coroutines are much lighter-weight and consequently you can start many more of them, and more quickly.
The internal workings are explained in the original design document https://github.com/Kotlin/KEEP/blob/master/proposals/coroutines.md which has a section on "Implementation Details".

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.

Firebase Android: What is the difference between getting callback from DatabaseReference's setValue via Task and DatabaseReference.CompletionListener?

I'm using the post-Google I/O 2016 Firebase database.
On a DatabaseReference, there is two similar methods, seem to only differ by the completion callback.
One is void setValue(Object value, DatabaseReference.CompletionListener listener), and another is Task<Void> setValue(Object value).
Are they interchangeable? The docs does not say anything about it and the Firebase Android SDK is closed source.
They are almost interchangeable. The key difference between the Task returned by setValue and the passed CompletionListener is the ability to avoid object leaks.
When you pass a CompletionListener to setValue, the Firebase SDK will hold on to that object reference (and all of that object's strong references, and so on) indefinitely, until the data is finally written at the server side. For Android apps, this can be particularly problematic because you could end up leaking an Activity reference, which is pretty expensive.
When you use a Task, you have the ability to add and remove listeners from that as needed, so if you're no longer interested in knowing if a write succeeded, you can free up the objects that were previously interested. In Android, there are overloads for adding listeners that automatically let a listener remove itself when the activity is stopped, so you don't have to arrange to do that yourself.
With Tasks, you can also arrange to have your callback invoked on a particular Executor, which is a convenient way to kick intense work off to another thread. With, CompletionListener, you'd have to arrange for that yourself in the callback itself.
I have a four-part blog series on the Tasks that are provided by Play services and the Java admin SDK. There is also formal documentation.

Categories

Resources