https://kotlinlang.org logo
#compose
Title
# compose
b

brandonmcansh

07/28/2020, 2:42 PM
Does anyone have a Flow<> example with Compose for observing a list?
z

Zach Klippenstein (he/him) [MOD]

07/28/2020, 2:44 PM
List
or
MutableList
?
b

brandonmcansh

07/28/2020, 2:45 PM
just an immutable one
the JetNews sample just has lambda's as return results for it's repository calls and looking at using usecases instead of passing the repository via args
z

Zach Klippenstein (he/him) [MOD]

07/28/2020, 2:47 PM
so you’ve got a
Flow<List<T>>
and you want to do something like
val currentList = listFlow.collectAsState(null)
?
b

brandonmcansh

07/28/2020, 2:47 PM
essentially ya
have it update a LazyColumnItems on change
is where my head was at at least
j

John O'Reilly

07/28/2020, 2:50 PM
There is a
Flow<T>.collectAsState()
extension function (wasn't sure if maybe that's what was being referred to by
collectAsState
reference above?)
z

Zach Klippenstein (he/him) [MOD]

07/28/2020, 2:50 PM
Copy code
val listFlow: Flow<List<T>> = …
val currentList: List<T>? = listFlow.collectAsState(null)
if (currentList == null) {
  LoadingUI()
} else {
  LazyColumnItems(currentList)
}
b

brandonmcansh

07/28/2020, 2:51 PM
oh boss
thank you
z

Zach Klippenstein (he/him) [MOD]

07/28/2020, 2:51 PM
if you have a
StateFlow
, you don’t need to provide the initial value yourself
b

brandonmcansh

07/28/2020, 2:53 PM
even better
thanks @Zach Klippenstein (he/him) [MOD]
Copy code
@Composable
internal fun BookmarkList(
        padding: Modifier,
        loadBookmarks: State<List<Bookmark>>
) {
    with(loadBookmarks) {
        ScrollableColumn(modifier = padding) {
            LazyColumnItems(value) { bookmark ->
                BookmarkCard(bookmark = bookmark) { editRequest ->
                    
                }
            }
        }
    }
}
there we go
Copy code
@Composable
private fun AppContent(
    navigationViewModel: NavigationViewModel,
    bookmarkViewModel: BookmarkViewModel
) {
    Surface(color = MaterialTheme.colors.background) {
        when (val screen = navigationViewModel.currentScreen) {
            Screen.Home -> {
                Crossfade(screen) {
                    HomeScreen(
                            navigateTo = navigationViewModel::navigateTo,
                            loadBookmarks = bookmarkViewModel.loadAll()
                    )
                }
            }
        }
    }
}
State<List<Bookmark>> from DI/passed args
z

Zach Klippenstein (he/him) [MOD]

07/28/2020, 3:07 PM
Passing a state in seems like a smell to me. Just pass the actual value in instead, it’s simpler API, simpler for testing, and simpler to reason about.
b

brandonmcansh

07/28/2020, 3:08 PM
fair reasoning
z

Zach Klippenstein (he/him) [MOD]

07/28/2020, 3:09 PM
Also making
this
a
State
i think makes this code harder to read. I’ve never seen any compose code do this, and i don’t see any
this
references in that snippet so are you even using it?
(unsolicited code review, sorry 😛)
b

brandonmcansh

07/28/2020, 3:10 PM
the
value
passed to LazyColumnItems
no keep it coming 🙂
z

Zach Klippenstein (he/him) [MOD]

07/28/2020, 3:11 PM
Ah, yes. I would definitely miss that in the first 2 or 3 reads of this code, and would definitely recommend just calling referencing the val directly (which is even less boilerplate if you just pass the actual value in)
b

brandonmcansh

07/28/2020, 3:11 PM
yep, that makes complete sense
looking into that now
AS is being dumb and is showing errors for kotlin pre-release but is still compiling fine so it's quite fun
z

Zach Klippenstein (he/him) [MOD]

07/28/2020, 3:12 PM
Irrelevant if you change to just pass the value in, but calling a
State
val
loadAnything
is confusing to me. The name “load*” reads like a verb, like it’s a function that performs a “load” action, but a state is more of a noun.
b

brandonmcansh

07/28/2020, 3:12 PM
yeah i had that named to match the usecase that I was attempting to pass in
agreed on the naming
z

Zach Klippenstein (he/him) [MOD]

07/28/2020, 3:13 PM
Ah, i see
2 Views