By delegate data class on observeAsState

Viewed 3015

I want to use the state by delegate syntax on observeAsState, but it report a error show there is no getValue method in data class.

@Composable
fun ComposeScreen(
    ...
) {
    val item: Item by viewModel.item.observeAsState(Item)  // there is an error in `(Item)`, it seems not delegate directly using the model of data class.
}

// viewModel
val item = itemRepository.item  // item is a LiveData 

// model
data class Item(
    ...
)

UPDATE

I find the solution reference other one's demo project, but I still not understand why do this.

import androidx.compose.runtime.getValue

val item: Item? by viewModel.item.observeAsState()
1 Answers

You need to import it mannualy, like this:

import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue

or

import androidx.compose.runtime.*

I believe it's a bug in Android Studio where it does not suggest to import it automatically.

[EDIT] You edited your question asking why we need that import, so I'll try to wrap it up:

When we want to delegate an assignment to a class using "by", we need to make a function called "getValue" with the "operator" modifier that returns the value in the correct type. It's the same logic for "setValue", we need to ask for a parameter of the right type and use "operator", allowing you to use "by" in a "var", besides "val".

What's happening there is that the function "getValue" and "setValue" are declared as extension functions, so it isn't enough to import "State", you also have to import the top level extension functions that are in a separated file.

Let me know if that explanation was enough, I took me a while to understand that, even thought that the documentation was out of date, by I was missing the import.

P.S. Here are the two functions in Compose's code, as you can see, they extends the "State" class.

inline operator fun <T> State<T>.getValue(thisObj: Any?, property: KProperty<*>): T = value

inline operator fun <T> MutableState<T>.setValue(
        thisObj: Any?, property: KProperty<*>, value: T) {
    this.value = value
}
Related