oday
09/21/2022, 12:08 PMisNetworkError
field that I start to get this error? if I remove it the error will be gone…oday
09/21/2022, 12:08 PModay
09/21/2022, 12:08 PModay
09/21/2022, 12:09 PModay
09/21/2022, 12:20 PModay
09/21/2022, 12:24 PMval searchState = combine(
arrayOf(
searchText,
cities,
showProgressBar,
showClearButton,
isOtherError,
isNetworkError
).asIterable()
) {
SearchState(
it[0] as String,
it[1] as List<City>,
it[2] as Boolean,
it[3] as Boolean,
it[4] as Boolean,
it[5] as Boolean
)
}
oday
09/21/2022, 12:24 PModay
09/21/2022, 12:24 PMhfhbd
09/21/2022, 1:13 PMhfhbd
09/21/2022, 1:15 PMNick Allen
09/21/2022, 1:21 PMisOtherError
and isNetworkError
. Since these are read by separate coroutines, they are read in parallel, with no mechanism to keep them in sync, so you could end up with a SearchState
that doesn’t make sense, because some of the source `Flow`s haven't caught up, mixing stale data with new data. Keep data together if it's used together, even if that means creating some extra data classes. The grouping will avoid data getting out of sync and you'll have less parameters into your combine
because the parameter count will grow with number of dependencies, not the number of properties in your resulting object.oday
09/21/2022, 4:38 PModay
09/21/2022, 4:39 PMNick Allen
09/21/2022, 5:08 PMclass MyClass {
val someInternalStateOrDependency: Flow<Exception> = ...
val thisInt: Flow<Int> = someInternalStateOrDependency.map { it.theInt }
val thatString: Flow<String> = someInternalStateOrDependency.map { it.theString }
}
val otherFlow = combine(myClass.thisInt, myClass.thatString, ...) { theInt, theString, ... -> ... }
then swap that out for
class MyClass {
val someInternalStateOrDependency: Flow<Exception> = ...
val allTheDataNeededFromHere: Flow<MyData> = someInternalStateOrDependency
.map { MyData(it.theInt, it.theString) }
}
val otherFlow = combine(myClass.allTheDataNeededFromHere, ...) { (theInt, theString), ... -> ... }
Nick Allen
09/21/2022, 5:08 PModay
09/21/2022, 9:24 PModay
09/22/2022, 4:21 PModay
09/22/2022, 4:22 PMNick Allen
09/23/2022, 12:32 PModay
09/23/2022, 12:34 PMNick Allen
09/23/2022, 12:36 PModay
09/23/2022, 12:56 PModay
09/23/2022, 12:56 PMNick Allen
09/23/2022, 12:58 PModay
09/25/2022, 11:03 AMsomeInternalStateOrDependency
is, can you show me how you would write it for my case? Literally? if you have timeoday
09/26/2022, 11:34 AMNick Allen
09/26/2022, 4:42 PMsearchText
, showProgressBar
, showClearButton
. They all are reflective of the onSearchTextChanged
value. After searchText.value = text
, your data is inconsistent since showProgressBar
and showClearButton
are not updated yet. This is the sort of thing where you want data that was calculated based off the same event (can be a method call like you have or an item in some dependent Flow
) to be together. So you could do a SearchState
data class, with a MutableStateFlow<SearchState>
that you set at once.
Relooking at your example, instead of combine, you could go with a mySearchState: MutableStateFlow<SearchState>
and in your methods that update the state, you can call:
val isNotEmpty = text.isNotEmpty()
mySearchState.update {
it.copy(
searchText = text,
showProgressBar = isNotEmpty,
showClearButton = isNotEmpty
)
}
Maybe this or something similar is what you ended up with. Btw, when you do find a simpler solution that works for you, it's nice to actually post what it was, so others benefit from what you figured out.oday
09/27/2022, 9:04 AModay
09/27/2022, 9:04 AM