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

Colton Idle

04/24/2020, 1:11 AM
@Brian Gardner your droidcon online session today was really good and it has me excited!
l

Leland Richardson [G]

04/24/2020, 5:55 AM
Was it recorded? I have seen a ton of positive feedback about it and would love to check it out
c

Colton Idle

04/24/2020, 6:52 AM
@Leland Richardson [G] yep. Should be recorded and going onto droidcon videos soon. I'll ping ya if I see it. 😄
b

Brian Gardner

04/24/2020, 2:18 PM
Thanks! I’m glad you liked it! I had a ton of fun with the session and I’m looking forward to making more video content soon
👍 1
l

Leland Richardson [G]

04/27/2020, 9:01 PM
@Brian Gardner this was great. really nice intro for people. I’m a bit curious about the state issue you mentioned with AdapterList. Is this a known issue reported somewhere? cc @Ryan Mentley Also, i’m curious if you intentionally were saying to use
mutableStateOf(...)
where you used it instead of
state { ... }
. The latter seems more correct based on the usage.
r

Ryan Mentley

04/27/2020, 9:02 PM
Which state issue? Timecode?
b

Brian Gardner

04/27/2020, 9:03 PM
l

Leland Richardson [G]

04/27/2020, 9:04 PM
in the video above, he is creating a toggleable button in each item of an adapterlist but said that it wasn’t updating when the state would get changed. My hunch is that the problem was actually just that mutableStateOf was being used instead of
state
though.
b

Brian Gardner

04/27/2020, 9:04 PM
I likely wasn’t intentional about the state part. Why would the
mutableStateOf()
work differently than
state
?
l

Leland Richardson [G]

04/27/2020, 9:06 PM
mutableStateOf
is like a constructor, and will create a new instance each time (with the value you pass in). The
state
function is a composable function which will only execute the
init
lambda the first time, and it will remember the instance each time. when creating state ina composable function, this is usually what you want. it is basically shorthand for
remember { mutableStateOf(init()) }
r

Ryan Mentley

04/27/2020, 9:07 PM
The
mutableStateOf
in the preview, I think, is the one that probably should lost be
state
b

Brian Gardner

04/27/2020, 9:08 PM
Ok, so creating the mutable state won’t trigger a recompose unless it’s wrapped in a
remember{}
block inside the composable function?
r

Ryan Mentley

04/27/2020, 9:09 PM
The code looks...otherwise mostly correct, but there's one suspicious bit. @Leland Richardson [G] is it valid to pass a
MutableState
directly like this? https://github.com/BrianGardnerAtl/JetpackComposePlayground/blob/adapter-list-state-spike/app/src/main/java/tech/briangardner/composeplayground/MainActivity.kt#L58
l

Leland Richardson [G]

04/27/2020, 9:09 PM
@Brian Gardner it does actually trigger an update… but when it recomposes the function, you just create a different mutable state instance (initialized to the same original value as before), so it doesn’t look like it’s doing anything
r

Ryan Mentley

04/27/2020, 9:09 PM
or should the value be passed directly?
l

Leland Richardson [G]

04/27/2020, 9:10 PM
it’s valid to do either
b

Brian Gardner

04/27/2020, 9:10 PM
ah ok, I didn’t realize it was calling the composable function again to recreate the view. I wasn’t sure how the recompose step worked but that makes sense
r

Ryan Mentley

04/27/2020, 9:11 PM
alright, in that case that does look like it's probably an AdapterList bug, because the rest of the mutable state code outside of the preview looks correct
I'd have to debug it to be sure, though.
l

Leland Richardson [G]

04/27/2020, 9:11 PM
yeah it calls the function again. similar to react, flutter, etc, you want to write your composable functions as if they can be called “again” at any time, so if the function itself is introducing the state, you want to make sure and hold onto it properly (hence, use remember or state)
b

Brian Gardner

04/27/2020, 9:13 PM
Another question I have is where it’s appropriate to create the state, since the functions can be called again. It seems like the state should be declared at the top-level, ‘screen’ component and passed down to the children. At least if the view state needs to change based on user interaction
l

Leland Richardson [G]

04/27/2020, 9:17 PM
there’s a whole can of worms that can be opened by that question… more or less, i try to think of it as create it in the place where the state is “owned”. That can be hard to define, but in general a good “rule of thumb” first candidate is going to be the closest ancestor composable where the value is used entirely “below” it, and nowhere else. If that scope changes, just move the state “up” until it is satisfied again
but there’s a lot more that goes into it and i might give a different answer depending on the context.
for instance, if there’s some state variable like “current logged in user”, that is going to be used at a much higher level than something more locally scoped or even just something less business-logic-specific and more ui-logic specific
b

Brian Gardner

04/27/2020, 9:20 PM
That makes sense. The main scenario I think of is loading data from a database (or web server). I can setup the state when the data loads but when I need to modify the data based on the user interaction, how do I update the screen with the new data?
Assuming the ViewModel (or presenter) handles the data loading and updates, would I just create a new composable with the updated data or is there a better way to swap it out
l

Leland Richardson [G]

04/27/2020, 9:22 PM
in those cases i think the better thing is to use something other than state (like LiveData or Flow etc.) and then join that data into the composable hierarchy using state, but keep state as an implementation detail
you can see how this is done with some of our interop libraries with Rx and LiveData
b

Brian Gardner

04/27/2020, 9:23 PM
Yeah, I saw that compose has the flow/rxjava to state stuff now which is cool. I’ll have to look into that more.
l

Leland Richardson [G]

04/27/2020, 9:23 PM
but in this case it is important to leverage tools such as
onCommit
to do it properly
also we will be releasing some new APIs around coroutines and such that will make a lot of this really really nice if your data layer uses suspend functions
b

Brian Gardner

04/27/2020, 9:24 PM
Sweet! We’re definitely moving towards suspend functions for our data layers so that will be nice
l

Leland Richardson [G]

04/27/2020, 9:25 PM
nice
b

Brian Gardner

04/27/2020, 9:25 PM
I haven’t messed with
onCommit
or
onActive
too much so I’ll look into those next
Thanks for talking through this stuff with me!
l

Leland Richardson [G]

04/27/2020, 9:26 PM
no problem!
thanks for creating such good content. it was a very well done live coding example
also, if you can, can you try updating your example to use
state
and see if that fixes the adapterlist bug you filed?
b

Brian Gardner

04/27/2020, 9:27 PM
I’m glad you liked it! I can take some time tomorrow morning to rework my sample to see if using
state
works
l

Leland Richardson [G]

04/27/2020, 9:28 PM
awesome, thanks!
2 Views