Search code examples
scrollandroid-jetpack-composeandroid-actionbar

Laggy performance when updating padding on scroll (Collapsing TopBar)


I have a Scaffold with a LargeTopBar and nestedScroll to collapse the bar on content scroll, everything looks good on simulator but performance is very laggy on real device (running in release mode).-

val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
    topBar = {
        TopAppBar(
            title = {
                Text(currentScreen.route)
            },
            scrollBehavior = scrollBehavior,
            colors = TopAppBarDefaults.topAppBarColors(
                containerColor = Color.Transparent,
                scrolledContainerColor = Color.Black.copy(alpha = 0.75f),
                navigationIconContentColor = Color.Black,
                titleContentColor = MaterialTheme.colorScheme.primary,
                actionIconContentColor = Color.Black
            )
        )
    },
) { padding ->
    Box {
        Background()
        MainNavHost(
            modifier = Modifier.fillMaxSize(),
            navController = navController,
            contentPadding = padding
        )
    }
}

If I just don't update the contentPadding by removing

contentPadding = padding

everything works perfectly smoothly. Any idea of what I might be missing to optimize this animation?

EDIT

Also, seems that the issue is related to the NavHost, as removing it fixes the problem. So, what's the right way to set the NavHost to avoid performance issues with this scrolling feature?


Solution

  • So after hours of confusion and anger, this was a noob mistake.

    Just in case someone faces similar issues, and to remind the importance of remember on heavy operations during recomposition, inside MainNavHost I was reading and parsing a mock json with some data, which happened on every animation frame, so something as simple as changing.-

    val jsonString = readJsonFromAssets(context, "games.json")
    val gson: Gson = GsonBuilder()
            .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
            .create()
    val games: Map<String, List<Game>> = gson.fromJson(jsonString, object : TypeToken<Map<String, List<Game>>>() {}.type)
    

    for

    val jsonString = remember { 
        readJsonFromAssets(context, "games.json") 
    }
    val gson: Gson = remember { 
        GsonBuilder()
            .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
            .create() 
    }
    val games: Map<String, List<Game>> = remember { gson.fromJson(jsonString, object : TypeToken<Map<String, List<Game>>>() {}.type) }
    

    completely did the trick.