Nathan Castlehow
03/16/2021, 4:30 AMMutableStateFlow
. I then want to “proxy” these through my view model to the view and expose them as something that the view can bind to. I want to avoid exposing them to the view as flows and then calling collectAsState
inside the view as i want to keep most things inside the view model.Nathan Castlehow
03/16/2021, 4:31 AMderivedStateOf
but can’t see how. The other option was to collect these flows in the view model and then populate mutableState
values but these seems messy.Adam Powell
03/16/2021, 4:32 AMMutableStateFlow
, are they internal MutableStateFlow
properties of the viewmodel, or passed as constructor parameters or similar?Nathan Castlehow
03/16/2021, 4:35 AMAdam Powell
03/16/2021, 4:45 AMAdam Powell
03/16/2021, 4:45 AMcollectAsState
might be the right thing hereZach Klippenstein (he/him) [MOD]
03/16/2021, 4:49 AMI want to keep most things inside the view modelI would too, but exposing a
StateFlow
of values for the view to observe is keeping “most things” inside the view model. I think that’s widely regarded as a very reasonable boundary. As long as the values are specifically designed to be consumed by the view (might require mapping inside your view model).Adam Powell
03/16/2021, 4:51 AMStateFlow
in my code. Not really enough to write about yet, but I tend to lean on the former quite a bit these days, especially since snapshotFlow {}
is aroundAdam Powell
03/16/2021, 4:52 AM.stateIn
I'll usually lean on StateFlow
but I end up using mutableStateOf
instead of MutableStateFlow
almost every timeNathan Castlehow
03/16/2021, 5:04 AMAdam Powell
03/16/2021, 5:06 AMAdam Powell
03/16/2021, 5:06 AMAdam Powell
03/16/2021, 5:06 AMAdam Powell
03/16/2021, 5:07 AMAdam Powell
03/16/2021, 5:09 AMMutableStateFlow
is kind of this weird case, like Rx Subjects, where it's always a bridge from hot code, and in nearly all cases I've encountered snapshot state ends up being more useful in those code paths for meAdam Powell
03/16/2021, 5:10 AMMutableStateFlow
I try to push it either to snapshot state or to a cold flow with a well-defined scope for a .stateIn
operator and I end up happier with the resultNathan Castlehow
03/16/2021, 5:51 AMState
provided by compose yeah? So my impression is that there is no sort of collectAsState
equivalent that can be used outside of composables so options are 1) use collect as state in composable composable (which works but adds sort of an extra layer) 2) Change the repository to return a State
value 3) Collect the flow in the view model and populate State
with it. That covers it right?Nathan Castlehow
03/16/2021, 5:51 AMAdam Powell
03/16/2021, 2:01 PMsnapshotFlow {}
returns a Flow
that can be used out of composition to observe the changing values of a function that returns the result of evaluating snapshot state, and the other lower level snapshot APIs may be used as well.Adam Powell
03/16/2021, 2:02 PMState
or values computed from it" - it's not necessary to expose the actual State
objects in the public interface of a class for snapshot state observation to work.Nathan Castlehow
03/17/2021, 2:20 AMZach Klippenstein (he/him) [MOD]
03/17/2021, 2:16 PMFlow
or StateFlow
-typed property) is that it’s self-documenting that the value is expected to change – you can see that just by looking at the type. Also, explicit stream types are useful in interfaces for communicating to implementors that the implementations should be reactive.
In a world where a bunch of those have been replaced by regular old vals, my instinct is to be worried that it could become very tricky to look at code in the middle layers and figure out if things are reactive or not, leading to bugs where people forget to check, and assume that something will cause recompositions when it won’t, or where someone will implement an interface without realizing that the interface contract requires implementations to be backed by snapshot states.Adam Powell
03/17/2021, 2:38 PM@Stable
, but yes, you're not alone in being nervous about it. It was a source of a lot of debate with Yigit, Sergey and others on the arch components team as this was all getting off the ground.Zach Klippenstein (he/him) [MOD]
03/17/2021, 2:46 PMZach Klippenstein (he/him) [MOD]
03/17/2021, 2:47 PMAdam Powell
03/17/2021, 2:52 PMAdam Powell
03/17/2021, 2:54 PMAdam Powell
03/17/2021, 2:55 PMAdam Powell
03/17/2021, 2:56 PM.value
is super broken as a concept, which we learned the hard way with LiveData
) When cold sources are still pushed toward Flow
the question doesn't tend to come up as oftenAdam Powell
03/17/2021, 3:00 PMStateFlow
and particularly MutableStateFlow
in a weird limbo of, "which do I use when and why?" when you're in compose-facing code, and for my own part I've found snapshots a lot easier and more pleasant to work with in places where I'd otherwise use StateFlow
. There are certainly exceptions; you'll note that Recomposer
uses StateFlow
in a couple places because it was a natural choice thereAdam Powell
03/17/2021, 3:02 PMAdam Powell
03/17/2021, 3:02 PMAdam Powell
03/17/2021, 3:03 PMAdam Powell
03/17/2021, 3:04 PMAdam Powell
03/17/2021, 3:04 PMAdam Powell
03/17/2021, 3:05 PMZach Klippenstein (he/him) [MOD]
03/17/2021, 3:08 PMZach Klippenstein (he/him) [MOD]
03/17/2021, 3:08 PMAdam Powell
03/17/2021, 3:09 PMAdam Powell
03/17/2021, 3:10 PMAdam Powell
03/17/2021, 3:11 PMAdam Powell
03/17/2021, 3:12 PMLazyColumn
DSL changes not being recomposed in timeAdam Powell
03/17/2021, 3:12 PMval items = remember { mutableStateListOf<String>() }
LazyColumn {
items(items.size) { index ->
Text("Item ${items[index]}")
}
}
Adam Powell
03/17/2021, 3:14 PMLazyColumn
list adapter, things get really interesting if you try to programmatically scroll the list from an arbitrary user code path and suddenly there are fewer items than items.size
returned since the last recompositionAdam Powell
03/17/2021, 3:18 PMval currentDslBlock by rememberUpdatedState(dslBlockParameter)
val adapter by remember { derivedStateOf { ListAdapter().apply(currentDslBlock) } }
then derivedStateOf
will re-evaluate its expression whenever it's read - pull-based, not push-based - if any snapshot state accessed in the build process changed since last timeAdam Powell
03/17/2021, 3:18 PMby lazy {}
Adam Powell
03/17/2021, 3:19 PMAdam Powell
03/17/2021, 3:21 PMAdam Powell
03/17/2021, 3:22 PMZach Klippenstein (he/him) [MOD]
03/17/2021, 3:28 PMAdam Powell
03/17/2021, 3:30 PMAdam Powell
03/17/2021, 3:31 PMAdam Powell
03/17/2021, 3:32 PMZach Klippenstein (he/him) [MOD]
03/17/2021, 3:33 PM