https://kotlinlang.org logo
#compose-android
Title
# compose-android
y

Yusuf Ibragimov

03/29/2024, 10:07 AM
Hi everyone, I have a question about the stability of the compose screen and smart recomposition. I read all documentation related to this topic and I make my composable to use stable parameters but when I check recomposition counts by layout inspector. Is there anyone to discuss this topic?
Copy code
@Composable
fun SettingsScreen(viewModel: SettingsViewModel = hiltViewModel()) {

    val uiState by viewModel.uiState.collectAsStateWithLifecycle()
    val scrollState = rememberScrollState()

    if (uiState.isLangSheetOpen) {
        SelectLangBottomSheet(
            langList = uiState.languages,
            code = uiState.selectedLanguage ?: "en",
            onDismiss = viewModel::dismissLangSheet,
            onClickBtn = viewModel::setLanguage
        )
    }

    Scaffold(
        modifier = Modifier.fillMaxSize(),
        containerColor = DavrTheme.backgroundColors.secondary
    ) {
        Column(modifier = Modifier.verticalScroll(scrollState)) {
            SettingsContent(
                topPadding = it.calculateTopPadding(),
                uiState = uiState,
                onAction = viewModel::onAction
            )
        }
    }

}

@Composable
internal fun SettingsContent(
    topPadding: Dp,
    uiState: SettingsUiState,
    onAction: OnAction
) {
    Box(
        modifier = Modifier
            .height(topPadding)
            .background(DavrTheme.backgroundColors.secondary)
    )
    UserInfoContent(
        uiState = uiState,
        onNotificationClick = { onAction(UiAction.NotificationClick) },
        navigateIdentification = { onAction(UiAction.NavigateIdentification) }
    )
    BankOperationsContent(uiState.bankOperations, onAction)
    SupportOperationsContent(uiState.supportOperations, onAction)
    SettingsOperationsContent(uiState.settingsOperations, onAction)
    LogOutContent(onAction)
}
this is my screen's code snippet
i use strong skippable mode, finally after that I achieve my goal, why skipping mode isn't working without this mode?
s

Sergey Y.

03/29/2024, 3:39 PM
Recompositions are not necessarily bad; they are often normal and expected. However, if you want to understand what's causing recompositions in your UI, there are a few tools you can use. First, the Compose compiler reports can be very helpful. These reports provide a text overview of your composable functions, including their attributes and states, along with a stability value. This can give you an idea of where potential issues might lie. Additionally, the Android Studio debugger is a great tool for inspecting recompositions. It displays the Composition State and clearly shows which attributes triggered a recomposition.
Like here in my case:
y

Yusuf Ibragimov

03/30/2024, 7:09 AM
thanks for a broad answer, but read all of this stability information and I make all my composable parameters stable, but when I check recomposition counts on Layout Inspector, recomposition cannot be skipped. Skipping recomposition works with strong skipping mode which I told you above.
s

Sergey Y.

03/30/2024, 7:22 AM
This indicates that some input attributes are changing. Using a debugger and setting a breakpoint at the right place will reveal what is changing. As for strong skipping mode, it only proves that some attributes are unstable or unequal, since this mode essentially relaxes equality checks between states.
My guess is that the ViewModel is definitely seen as unstable from the perspective of the Compose compiler, and its instance is captured by click callbacks. This automatically marks the callbacks as "changed" for every recomposition.
y

Yusuf Ibragimov

03/30/2024, 7:37 AM
Yeah, I am searching what is main reason. If we always use strong skipping mode, why documentation tell us use stable objects, use immutable collections?. Is there any instruction to create pure composable screens?
s

Sergey Y.

03/30/2024, 7:38 AM
To verify this, you can observe it using a debugger, or you can annotate the ViewModel class with one of the Compose runtime stability annotations, either Stable or Immutable. The specific annotation doesn't matter in this context.
y

Yusuf Ibragimov

03/30/2024, 7:38 AM
Could we ask about that from @Manuel Vivo? Who is responsable stability of compose?
Yeah, I check my composable but I cannot acheive my desired condition without strong skipping mode.
s

Sergey Y.

03/30/2024, 7:52 AM
Well, I would suggest not fixating on "redundant" recompositions, especially at the beginning. Recomposition doesn't mean the screen is fully redrawn; it's simply a reaction to changes. Each component further down can skip recomposition if there are no relevant changes for it. The main guideline is to avoid placing your logic directly in the bodies of composable functions and not to base your logic on recompositions.
👍 1
y

Yusuf Ibragimov

03/30/2024, 9:16 AM
Yeah, that's right but if we write one structure, it's a our main template to create composables. I just wondering about future, if something changes, should we change our whole project?. Right , it isn't very big problem, I just try to find carifications, thanks for discussing.🫡
b

Ben Trengrove [G]

04/01/2024, 7:55 PM
At a quick read, your view model is unstable and so the function references are being recreated on recomposition and that means the composable isn't skipped because its inputs have changed. Strong skipping mode remembers them for you
Strong skipping isn't in the stability documentation yet because it's still experimental. This is changing soon though, it is safe to use if you just want to continue with that