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

wasyl

10/21/2019, 10:49 PM
I tried searching but didn’t find anything that helps and I’m confused. Should I expect the views to change/recompose when passing
@Model
into another
@Composable
function? Something like:
Copy code
@Composable
fun App() {
    val appState = +memo {
        ParentModel(
            listOf(
                ChildModel("Item 1", false),
                ChildModel("Item 2", true)
            )
        )
    }
    Column {
        appState.childModels.forEach { item ->
            Item(item)
        }
    }
}

@Composable
fun Item(item: ChildModel) {
    ListItem(
        text = { Text(item.description) },
        trailing = {
            Checkbox(
                checked = item.checked,
                onCheckedChange = { item.checked = it })
        }
    )
}

@Model
data class ParentModel(
    var childModels: List<ChildModel>
)

@Model
data class ChildModel(
    var description: String,
    var checked: Boolean
)
?
I think I tried everything, and the only thing that triggers the update is when I introduce some completely irrelevant state in the
Item
function and change it as well
g

George Mount

10/21/2019, 11:11 PM
If the problem is that when you update the list (add/remove items) you aren't seeing recomposition, you should be using a
ModelList
instead
listOf
. Try replacing
listOf
with
modelListOf
.
Or is it that the check/uncheck isn't working?
👆 1
w

wasyl

10/21/2019, 11:14 PM
Hey, thanks for answering. The problem isn’t adding to the list (although later on it would be, so thanks for the tip!). The problem that I have is that even though I pass
@Model
instance to a composable functions, changes to that model don’t trigger the recomposition. Specifically in
fun Item(item: ChildModel)
I have
onCheckedChange = { item.checked = it }
. I’d expect that part of subtree to be recreated, while it isn’t
Yep, check/uncheck exactly. Only saw that message after posting mine
g

George Mount

10/21/2019, 11:15 PM
I think we typed at the same time 🙂
I haven't seen this problem. I'm trying it locally.
👍 1
hmm... your example works for me. I'm working against tip-of-tree.
I used:
Copy code
@Composable
fun ListItem(text: @Composable() () -> Unit, trailing: @Composable() () -> Unit) {
    Row {
        text()
        trailing()
    }
}
w

wasyl

10/21/2019, 11:37 PM
The code above is basically exactly what I’ve been trying, the only missing thing is
Copy code
setContent {  MaterialTheme { App() } }
in Activity’s
onCreate
. I should be up to date too,
a9891c6791
. My
ListItem
is
androidx.ui.material.ListItemKt#ListItem
Just tried again, copied the code verbatim + your ListItem. Clicking on checkboxes doesn’t change anything about the UI
Can you please post the entire file (activity I assume?) complete with imports? I’ll try that locally too. Also maybe I have some weird issue with dependencies? I basically added all
:ui:ui-*
dependencies to the module
I just checked again with
--rerun-tasks
to make sure it’s not some weird cache issue, and still doesn’t work 😕 I also synced the repo again, I’m on
8277cf7b6f
r

romainguy

10/21/2019, 11:57 PM
And you’re using
studiow
or
gradle studio
right?
w

wasyl

10/21/2019, 11:59 PM
Yep,
./gradlew studio
I just created a separate module, no success. Do these dependencies seem right?
Copy code
implementation(KOTLIN_COMPOSE_STDLIB)
~implementation(project(":ui:ui-android-view"))~
implementation project(":compose:compose-runtime")
implementation project(":ui:ui-core")
implementation project(":ui:ui-foundation")
~implementation project(":ui:ui-framework")~
implementation project(":ui:ui-animation")
implementation project(":ui:ui-layout")
implementation project(":ui:ui-text")
implementation project(':ui:ui-material')
Here’s the entire thing for completeness: https://gist.github.com/lwasyl/6ba58e6bd3334a7fb5504f8d9bd95803. I have to log off for now, but I’d appreciate any help and suggestions
Further experimentation:
Copy code
@Composable
fun Item(item: ChildModel) {
    val stubState = +state { 0 }
    ListItem(
        text = { Text("${item.description} [${stubState.value} changes]") },
        trailing = { Checkbox(checked = item.checked, onCheckedChange = { }) },
        onClick = {
            item.checked = !item.checked
            stubState.value++
        }
    )
}
With this I get different texts when I click on the items, but the checked state still doesn’t change. But when I debug the calls to
Text(...
I can see that the model has an updated
checked
value
Well, I know what the issue was. I was working within
demos
project, so I didn’t have compose plugin applied 😞
I’ve added
AndroidXUiPlugin
plugin,
kotlinPlugin project(path: ":compose:compose-compiler", configuration: "embeddablePlugin")
dependency and
useIR
option to Kotlin plugin and it works. I had a feeling it’s something with dependencies, didn’t realize it would be that obvious
a

Andrey Kulikov

10/22/2019, 10:35 AM
what probably happened for you is the compiler wasn't applied so no additional code was generated for @Model marked class and thus no recomposition happened
w

wasyl

10/22/2019, 10:44 AM
Yep, sounds right. Sorry for the hassle, was pretty silly mistake
l

Leland Richardson [G]

10/22/2019, 8:38 PM
This mistake isn’t actually that silly. I predict that this will happen to a LOT of people, myself included, until we figure out a way to trigger warnings or errors when we detect @Composable or @Model being compiled without the compose plugin. We don’t have an answer for this yet, but would like to figure it out soon. This is a big foot-gun and will cause people frustration in the near term 😕
👍 1
v

voddan

10/28/2019, 8:45 AM
@Leland Richardson [G] Mark
@Model
with
@Deprecated(error)
and then make your compiler plugin disable it 🤔
l

Leland Richardson [G]

10/28/2019, 6:06 PM
Yeah, this is a pretty good idea. we thought about this, or using the
@ExperimentalFeature
flag. IIRC there were some issues with this, and the messages that would result in other versions of android studio/kotlin would be pretty hard to understand what to do, so we decided against it i guess
when we figured out this was going to be a problem we didn’t have a ton of time left either. we will definitely try to have a more robust warning/plan here for future rollouts
👍🏼 1
4 Views