Compose state basics - devrath/ComposeAlchemy GitHub Wiki
- State is something that changes over time. Thus a value that changes over time is called a state
- This is not a state --->
const val TIME_OUT = 500
- This is kinda state but not completely a state ------->
var count = 0
- Observe that on click even if I modify the primitive state variable, the
Recomposition
of the text is not triggered. - Simple primitive states cannot tell composables when they get updated.
- The composable function needs to be recalled with a new value for recomposition to occur.
- This is because no mechanism behind the primitive variables tells composables for initiating the recomposition.
- This is the reason the
state
exists in composable.
Code
private var counterState = 0
@Composable
fun StatesWithPrimitiveDemoScreen(modifier: Modifier = Modifier) {
Scaffold(
modifier = Modifier.fillMaxSize()
) { padding ->
Box(
modifier = Modifier.fillMaxSize().padding(padding),
contentAlignment = Alignment.Center
) {
Button(
onClick = {
counterState++
}
) {
Text(text = "Current Value -> $counterState")
}
}
}
}
- State is a value that can change over time also the
appearance
or the position of a composable --> Then it would be compose state. - Also we use remember along with a state because the
remember
caches the the value across the recompositions so that the value is not set again and again and when the value is altered the value cached is updated the process is repeated. - When you update a state and updating the state causes something else to be modified apart from the UI it is attached to is called
side-effect
Code
@Composable
fun StatesWithComposeDemoScreen(modifier: Modifier = Modifier) {
var counterState by remember { mutableIntStateOf(0) }
Scaffold(
modifier = Modifier.fillMaxSize()
) { padding ->
Box(
modifier = Modifier.fillMaxSize().padding(padding),
contentAlignment = Alignment.Center
) {
Button(
onClick = {
counterState++
}
) {
Text(text = "Current Value -> $counterState")
}
}
}
}
code
@Composable
fun StatesWithComposeDemoScreen(modifier: Modifier = Modifier) {
var counterState by remember { mutableIntStateOf(0) }
Scaffold(
modifier = Modifier.fillMaxSize()
) { padding ->
Box(
modifier = Modifier.fillMaxSize().padding(padding),
contentAlignment = Alignment.Center
) {
Button(
onClick = {
counterState++
}
) {
Text(text = "Current Value -> $counterState")
}
}
}
}
- Here notice the side-effect occurs and the count gets infinitely updated and gets appended continuously.
- How this has happened because note the count mutable state must always be updated from normal lambda and not inside the compose scope
code
@Composable
fun StatesWithSideEffectDemoScreen(modifier: Modifier = Modifier) {
var counterState by remember { mutableIntStateOf(0) }
Scaffold(
modifier = Modifier.fillMaxSize()
) { padding ->
Box(
modifier = Modifier.fillMaxSize().padding(padding),
contentAlignment = Alignment.Center
) {
Button(
onClick = {
counterState++
}
) {
counterState++
Text(text = "Current Value -> $counterState")
}
}
}
}
Output
sideeffect.webm
- The
remember
is a caching mechanism used tocache
the variable that is kept the same across re-composition. - It is used because the variable is attained by a heavy computation and
cached
and does not need to perform the same operation every time on each re-composition. - When we use the
state
in combination withremember
always when needed.
var counterState by remember { mutableIntStateOf(0) }
-
remember state
---------> Here the state is cached on recomposition but not on orientation change since entire composables are re-drawn.
var counterState by remember { mutableIntStateOf(0) }
-
rememberSavable state
--> Here the state is cached onrecomposition
and theorientation change
and also acrossprocess-death
.
var counterState by rememberSavable { mutableIntStateOf(0) }
- If we just update the content of the state the composables that observe the state are not notified even if the contents of the state change.
- If we change the reference of the state the recomposition is triggered.
code
@Composable
fun UpdatingContentOfStateDemoScreen(modifier: Modifier = Modifier) {
var updateReference by remember { mutableStateOf(listOf("<-Item->")) }
var updateContentOfReference by remember { mutableStateOf(mutableListOf<String>("<-Item->")) }
Scaffold(
modifier = Modifier.fillMaxSize()
) { padding ->
Column(
modifier = Modifier.fillMaxSize().padding(padding)
) {
Column(
modifier = Modifier.fillMaxSize().weight(1F).background(color = Color.Cyan)
) {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.SpaceBetween
) {
Text(text = updateReference.toString())
Button(onClick = {
updateReference = updateReference.plus("<-Item->")
}) {
Text(text = "Update references")
}
}
}
Column(
modifier = Modifier.fillMaxSize().weight(1F).background(color = Color.DarkGray)
) {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.SpaceBetween
) {
Text(text = updateContentOfReference.toString())
Button(onClick = {
updateContentOfReference.add("<-Item->")
}) {
Text(text = "Update content of reference")
}
}
}
}
}
}
output