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()
There are three ways to declare a MutableState object in a composable: val mutableState = remember { mutableStateOf(default) } var value by remember { mutableStateOf(default) } val (value, setValue) = remember { mutableStateOf(default) }
Jetpack compose is stable and ready for production but Google still continues to bring new features to the library on every new release, some features are graduated to stable from experimental whilst new features or APIs are introduced as experimental.
Recomposition. In an imperative UI model, to change a widget, you call a setter on the widget to change its internal state. In Compose, you call the composable function again with new data. Doing so causes the function to be recomposed--the widgets emitted by the function are redrawn, if necessary, with new data.
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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With