New to compose, but I expected something like this...
# compose
c
New to compose, but I expected something like this to work but it does not. My activity has a field myTodoList mutableListOf<String> and it has items added to it by another source (right now I have a post delayed handler that waits for 5 seconds, and then adds ten items) and I expect the items to update this Screen composable, but nothing shows. I'm assuming it's because the state can't live in the activity? That actually doesn't really make sense I guess. Just want someone to look this over. Thank you!
Copy code
@Composable
private fun MyActivityScreen(items: List<String>) {
    val myThings = remember { mutableStateOf(items) }
    Column() {
        myThings.value.forEach {
            Text(text = it)
        }
    }
}
a
myThings
is not necessary I think. Use
items
directly.
k
LiveData.observeAsState() ?
c
@allan.conda using items directly didn't work.
@Kane Shih Do I have to use LiveData? What if that's a dependency that I don't want to pull in and I just want to do this with pure compose?
k
1 find a way to call
myThings.setValue
2 Kotlin Flow or RxJava -> to State
c
Hm. So I need to use Flow or Rx to use compose?
k
or find a way to trigger recomposition
but I think LiveData is still the best choice in your use case
c
That's what I thought
val myThings = remember { mutableStateOf(items) }
is used for? @Leland Richardson [G] am I doing something wrong here?
f
Your problem lies not in compose but with your list in your activity. The list needs to be observable if you want your composables to recompose on a change of the items in the list. Either use a Flow<List>, LiveData<List> or mutableStateOf(List), hand that over to your MyActivityScreen and observe it in there.
☝️ 3
c
@flosch so in my activitiy the field is defined as
Copy code
val listOfItems = mutableListOf<String>()
so if I just change that to mutableStateOf I should be good? I will try that now and let you know what happens. Thank you! I was not aware that I couldn't just use a regular list and pass it into a composable and then that composable converts it to an observable (aka. thats what I thought I was doing with my
val myThings = remember { mutableStateOf(items) }
statement
f
Yes that is what it does but only in your composable scope. If you change the value of
myThings
then it will be recomposed, but you said you changed
items
outside of your composable; that will not work
c
Oooh. Okay yeah that makes sense. Let me give it a shot. Appreciate your time and explanation @flosch
@flosch still does not trigger a recomposition it seems. Here is the composable
Copy code
@Composable
private fun MyActivityScreen(items: MutableState<MutableList<String>>) {
    Column() {
        items.value.forEach {
            Text(text = it)
        }
    }
}
And my activity defines a field
Copy code
val listOfItems = mutableStateOf(mutableListOf<String>())
and I add to the listOfItems via
Copy code
listOfItems.value.add("adsf")
f
Yea you will probably have to change the value of
MutableState
and not of the
MutableList
Copy code
val listOfItems = mutableStateOf(listOf<String>())

@Composable
private fun MyActivityScreen(items: State<List<String>>) {
    Column() {
        items.value.forEach {
            Text(text = it)
        }
    }
}

listOfItems.value = listOf("a")
listOfItems.value = listOf("a", "b" )
You could also use
mutableStateListOf
(LINK)
c
@flosch That worked! So basically mutable state can't use a mutable class/obj/reference Wish there was a lint check for that maybe? Also wish there was an easy way to take a list and copy or duplicate it. To get around it for now I started doing list.toMutableList() then call add(new value), then .toList(). Seems inefficient?
f
Copy code
data class State(val items: List<String>, ...)
val state = ...
state.copy(items = ...)
Immutable objects are the way to go with data driven architectures
c
Oooh. So just wrap it in a data class. Okay. I just thought it was interesting there was no .copy on a List. 👍 Thank you @flosch!