Maybe a weird question. But I have a mutableState ...
# compose
c
Maybe a weird question. But I have a mutableState that is accessible in my VM. Is there a way in the VM to observe changes of that state? Ideally I could do something like
init { myMutableState.collect { refresh() } }
c
c
The example there shows it in a launchedEffect, which I don't think i can have in my VM?
Unless I'm misunderstanding something (which admittedly. i need to go to sleep) 😅
c
It’s in a launched effect because it’s collecting the Flow.
snapshotFlow
just creates a normal
Flow
which can be collected anywhere. It requires Compose to be running for it to emit values (well, really, just the global Snapshot), but it doesn’t have to be collected within a
LaunchedEffect
. You can see examples of it being used in non-Compose classes in the Compose stdlib, such as in
SwipeableState
☝️ 2
🤘 1
t
@Colton Idle Who’s responsible to change the value of this
State
? VM? or its being exposed via another source ?
c
In my VM there is a service/class being injected in. That class has a SnapshotState. In my VM I want to take the service being injected and grab the snapshotState and observe it.
t
🤔 Exposing compose dependency (here SnapshotState) from data layer (i guess its a repo) is okay ? What if I want to use the repo in some non compose context? Why not expose a Flow instead and observe the value with
collect
?
c
Yeah, it seems like you’re going the wrong way with the reactive datatypes. You should be using classes like Flow that are not tied to Compose (or any UI toolkit) in the service layer, and then converting those to UI-specific types in the UI layer. Think about trying to unit test a
snapshotFlow
when the UI is not present; it won’t ever emit values. But if you expose a
Flow
, then you can easily unit-test collecting that flow without having that dependency on the UI stuff
For a similar reason, you also shouldn’t return
LiveData
from a Service/Repository layer, because it is also tied specifically to UI
c
Yeah that makes sense I just don't own this service so to speak. I definitely agree that it'd be preferable if it was the flow or something
For now though, it looks like I'm out of luck
a
snapshotFlow
is exactly the tool you’re looking for to kick off ongoing suspending work in response to changing snapshot state outside of composition. Just to make a comment against “tied to Compose”: Using snapshot state in a data layer object isn’t inherently wrong, it’s a tool like anything else. There are times where `Flow`s are more appropriate, but I wouldn’t be so quick to say that snapshot state doesn’t belong anywhere except in the UI. Adam went into some more detail about this here as well: https://kotlinlang.slack.com/archives/CJLTWPH7S/p1623337962396700?thread_ts=1623313858.334200&cid=CJLTWPH7S
c
@Alex Vanyo thanks for the great reference. So in my example... if I have this in my VM. How would I solve this with
snapshotFlow
?
init { myMutableState.collect { refresh() } }
a
It'd be something along the lines of
init { snapshotFlow { myMutableState }.collect { refresh() } }
c
Awesome. Will give that a shot