Hi, I am working on nested column in jetpack compo...
# compose
k
Hi, I am working on nested column in jetpack compose. I have one list which is huge amount of data coming from server. I was checked in Layout Inspector and I see that whenever my item is added in list it recompose and increase counts. So my doubt is if I add 100 item in list one by one, so my
Nested Column
will be
100 times recompose
? If not can someone help me on this please?
ListViewComposableActivity.kt
Copy code
class ListViewComposableActivity : BaseActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            AppBarScaffold(
                displayHomeAsUpEnabled = true,
                titleId = R.string.activity
            ) {
                ListViewItemStateful()
            }
        }
    }
}
ListViewItemStateful
Copy code
@Composable
fun ListViewItemStateful(
    viewModel: ListViewModel = koinViewModel(),
) {
    ItemViewListStateless(
        uiState = viewModel.uiState,
        isEnable = viewModel.isEnable,
        scanDeviceList = viewModel.scanResultList,
    )
}
ItemViewListStateless
Copy code
@Composable
fun ItemViewListStateless(
    uiState: State,
    isEnable: Boolean,
    scanDeviceList: SnapshotStateList<ScanResults>,
) {
    when (uiState) {
        INITIAL,
        FIRST -> {
            ListContent(isEnable, scanDeviceList)
        }
    }
}
ListContent
Copy code
@Composable
fun ListContent(isEnable: Boolean, scanDeviceList: SnapshotStateList<ScanResults>) {
    AnimatedVisibility(true) {
        Column(
            modifier = Modifier
                .padding(16.dp)
                .fillMaxSize()
                .verticalScroll(rememberScrollState()),
        ) {
            if (isEnable) {
                Column(horizontalAlignment = Alignment.CenterHorizontally) {
                    DeviceList(
                        scanDeviceList,
                        modifier = Modifier.align(Alignment.Start),
                    )
                }
            }
        }
    }
}
DeviceList
Copy code
@Composable
fun ColumnScope.DeviceList(
    scanDeviceList: SnapshotStateList<ScanResults>,
    modifier: Modifier = Modifier,
) {
    Spacer(modifier = Modifier.height(32.dp))
    AnimatedVisibility(
        scanDeviceList.isNotEmpty(),
        modifier = modifier
    ) {
        Column {
            Text(text = "Device List")
            scanDeviceList.forEachIndexed { index, scanResults ->
                Text(text = scanResults.device.name)
            }
        }
    }
}
ListViewModel.kt
Copy code
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.viewModelScope
import com.abc.app.common.BaseViewModel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class ListViewModel : BaseViewModel() {

    val scanResultList by lazy { mutableStateListOf<ScanResults>() }
    var isEnable by mutableStateOf(false)
        private set
    var uiState by mutableStateOf<State>(State.INITIAL)
        private set

    init {
        viewModelScope.launch {
            (0..10).forEach {
                delay(2000)
                scanResultList.add(ScanResults(Device("item $it")))
            }
        }
        isEnable = true
        uiState = State.FIRST
    }
}


data class ScanResults(val device: Device)
data class Device(val name: String)
enum class State {
    INITIAL,
    FIRST
}
I am adding few items in list to show in layout inspector
Screenshot 2023-01-13 at 16.57.13.png
In above image you can see the
DeviceList
is recompose 10 times. I checked in @Ben Trengrove [G]

Jetpack Compose: Debugging recomposition

around 6:40 min he tried to solve recompose issue and there skipped recomposition count is clear. So why it's showing count in my component tree in recomposition and skipped section? Many thanks
j
Have you tried using LazyColumn and providing the key? IT seems like Column isn't the right answer for you
k
Lazycolumn will not work with parent column
j
yes, that's why LazyColumn should be the parent column. I don't think you can work around performance issues if you keep adding items to normal Column. It wasn't implemented with that in mind
k
I got your hint, but I was a little bit confused. Do you have any working example for this ?
j
LazyColumn can accept single item or multiple items. If you want to do a big scrolling screen you can just add everything to LazyColumn. The static part can be embedded in a single item on top, and then the rest can be added via
items
k
Sure,I'll try, thanks..
@Jakub Syty I changed my
ListContent
to like this what you mention above
Copy code
@Composable
fun ListContent(isEnable: Boolean, scanDeviceList: SnapshotStateList<ScanResults>) {
    AnimatedVisibility(true) {
        LazyColumn(
            modifier = Modifier
                .padding(16.dp)
                .fillMaxSize()
        ) {
            if (isEnable) {
                item {
                    Text(text = "Device List")
                }
                item {
                    Spacer(modifier = Modifier.height(32.dp))
                }
                items(scanDeviceList) {
                    Text(text = it.device.name)
                }
            }
        }
    }
}
Why
SaveableStateProvider
is recomposing ?
j
That's the internals of LazyColumn. You shouldn't worry about that, just run the app minified and compare the performance
Confirm that performance issue is an issue
recompositions are not bad by themselves
k
Sure, thanks a lot