Here is my problem;
- When I add MyText composable in my Screen, I see all Logs (value1, value2, value3) which means it is recomposing every part of my code.
- However when I comment the MyText line, I see only value3 on Logcat
How can I fix this ? I know it is not a big problem here but just imagine we have a scrollable Column here and we are trying to pass ScrollState.value to My Text component. Because of this situation, our list becomes so laggy.
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Screen()
}
}
}
@Composable
fun Screen(){
var counter by remember {
mutableStateOf(0)
}
Log.i("RECOMPOSE","VALUE1")
Column() {
Text(text = "Just a text")
Log.i("RECOMPOSE","VALUE2")
Button(onClick = { counter = counter.plus(1) }) {
Text(text = counter.toString())
Log.i("RECOMPOSE","VALUE3")
}
MyText(counter)
}
}
@Composable
fun MyText(counter:Int){
Text(text = counter.toString())
}
EDIT There is main problem, with Scrollable Column;
@Composable
fun Screen(){
val scrollState = rememberScrollState()
Box() {
Column(modifier = Modifier
.verticalScroll(scrollState)
.padding(top = 50.dp)) {
//Some Static Column Elements with images etc.
}
MyText(scrollStateValue = scrollState.value) //Doing some UI staff in this component
}
}
@Composable
fun MyText(scrollStateValue:Int){
Text(text = scrollStateValue.toString())
}
CodePudding user response:
This behaviour is totally expected.
Compose is trying to reduce number of recompositions as much as possible. When you comment out MyText
, the only view that depends on counter
is Button
content, so this is the only view that needs to be recomposed.
By the same logic you shouldn't see VALUE1
logs more than once, but the difference here is that Column
is inline
function, so if it content needs to be recomposed - it gets recomposed with the containing view.
Using this knowledge, you can easily prevent a view from being recomposed: you need to move part, which doesn't depends on the state, into a separate composable. The fact that it uses scrollState
won't make it recompose, only reading state value will trigger recomposition.
@Composable
fun Screen(){
val scrollState = rememberScrollState()
Box() {
YourColumn(scrollState)
MyText(scrollStateValue = scrollState.value) //Doing some UI staff in this component
}
}
@Composable
fun YourColumn(scrollState: ScrollState){
Column(modifier = Modifier
.verticalScroll(scrollState)
.padding(top = 50.dp)) {
//Some Static Column Elements with images etc.
}
}