I'm struggling to understand why I should use `Sta...
# android
a
I'm struggling to understand why I should use
StateFlow
instead of
LiveData
. From what I can tell it's main benefits are 1) It's a Kotlin language feature rather than an Android library and 2) you can use intermediate "flow" operations on it rather than use a get()ter method to manipulate the data. That's pretty much it, right?
c
I think the main appealing aspect of Shared/State Flows is that you can use it in places where you don't necessarily need Lifecycle aware components such as Repositories. In the past people would often use LiveData which is a LIfecycle aware component in Non-Lifecycle aware places. And you can decouple your model from platform specific code. And the cherry on top is that you can use it on Kotlin Multi platform projects as well PS: If you by any chance don't know what Lifecycle aware components are here's a link to the documentation: https://developer.android.com/topic/libraries/architecture/lifecycle Usual examples of Lifecycle aware components are Activities and Fragments among others.
a
Thanks. I'm aware of the lifecycle. That is an advantage, I agree, although not one for me, because my Android apps are tied to Android. I've never used the cross platform stuff but it would open up that possibility sure. Thanks for the response.
👍 1
a
LiveData
doesn't work well with Kotlin due to its lack of null safety. This along with the easiness of transforming `StateFlow`s are more than enough to make
StateFlow
a better choice. For example, it is extremely verbose to create a derived
LiveData
from multiple `LiveData`s, but with `StateFlow`s, it is as simple as using
combine
on them.
a
Yeah, I've not needed that feature, but it's good. I've just started to refactor code and the main thing for me, which comes from the "not tied to android" thing is that I don't need an activity context to observe its changes.
l
Also... No backpressure support with livedata.
a
Yeah this all comes with my second point in the original post.
h
Another benefit: You could share your code with non android targets, like desktop or web
l
Backpressure is a separate issue:
Copy code
fun currTime() = System.currentTimeMillis()
 fun threadName() = Thread.currentThread().namevar start: Long = 0
 
 fun testBackPressure() { 
         (1..5)
                 .asFlow()
                 .onStart { start = currTime() }
                 .onEach {
                     delay(1000)
                     print("Emit $it (${currTime() - start}ms) ")
                 }
                 .collect {
                     print("\nCollect $it starts (${currTime() - start}ms) ")
                     delay(3000)
                     println("Collect $it ends (${currTime() - start}ms) ")
        }
 }
With flow you get all values. Test it out with LiveData.
a
That's nice, thanks for your code. I count
onEach
et al as intermediate operators. What else would you call them?
l
The point isn't the usage of onEach, it's the delay
a
Okay, cool. Thank you for the clarification.
l
If you have a producer which produces events faster then downstream can consume them (as in the code above) with Flow the events get suspended and eventually collected. With LiveData they get lost
a
It is nice, it's something I've done with coroutines and delay before but aligning with the data will be nicer.
e
My TLDR; StateFlow can do what LiveData can, but more. So it’s more flexible. Things like using operators and going between threads. In my mind if I could choose I see no reason to go with LiveData.