androidkotlinandroid-jetpack-composeandroid-navigation

Constant GPU rendering by Icons


I have a problem with Icon() component which looks like is redrawing constantly. I don't understand this behavior, I've tried almost everything, it looks like a bug. I don't see this behavior in other apps. When I comment out this component it's not redrawing. I'm using code below to log recomposition and it looks normal.

Image of GPU rendering

class Ref(var value: Int)
inline fun LogCompositions(tag: String, msg: String) {
    if (BuildConfig.DEBUG) {
        val ref = remember { Ref(0) }
        SideEffect { ref.value++ }
        Log.d(tag, "Compositions: $msg ${ref.value}")
    }
}

Here are the results:

D Compositions: AppEntry() 0
D Compositions: NavigationBarIcon(2131755275) 0
D Compositions: NavigationBarIcon(2131755276) 0
D Compositions: NavigationBarIcon(2131755279) 0
D Compositions: NavigationBarIcon(2131755275) 1
D Compositions: NavigationBarIcon(2131755276) 1
D Compositions: NavigationBarIcon(2131755279) 1

Here is the rest of the code:

@Composable
fun AppEntry(
    windowSizeClass: WindowSizeClass,
    appState: AppState = rememberAppState(
        windowSizeClass = windowSizeClass,
    ),
) {
    val snackBarHostState = remember { SnackbarHostState() }

    LogCompositions(tag = "TEST", msg = "AppEntry()")
    Scaffold(
        containerColor = Color.Transparent,
        contentColor = MaterialTheme.colorScheme.onBackground,
        contentWindowInsets = WindowInsets(0, 0, 0, 0),
        bottomBar = {
            if (appState.shouldShowBottomBar)
                NavigationBottom(
                    destinations = appState.topLevelDestinations,
                    currentDestination = appState.currentDestination,
                    onNavigateToDestination = appState::navigateToTopLevelDestination,
                )
        },
        snackbarHost = { SnackbarHost(snackBarHostState) },
    ) { paddingValues ->
        AppNavHost(
            appState = appState,
            modifier = Modifier
                .padding(paddingValues)
                .fillMaxSize()
        )
    }
}
@Composable
fun NavigationBottom(
    modifier: Modifier = Modifier,
    currentDestination: NavDestination?,
    onNavigateToDestination: (route: String) -> Unit,
    destinations: List<Navigation>,
) {
    NavigationBar(modifier = modifier) {
        destinations.forEach { item ->
            val selected = currentDestination.isTopLevelDestinationInHierarchy(item.route)
            val icon = item.drawableRes
            NavigationBarItem(
                icon = {
                    LogCompositions(tag = "TEST", msg = "NavigationBarIcon(${item.name})")
                    // Problem
                    Icon(imageVector = icon, contentDescription = null)
                },
                label = {
                    Text(stringResource(item.name))
                },
                selected = selected,
                onClick = { onNavigateToDestination(item.route) },
                modifier = Modifier
            )
        }
    }
}
object AppIcons {
    val Cart = Icons.Rounded.ShoppingCart
    val List = Icons.Rounded.List
    val Info = Icons.Rounded.Info
}
sealed class Navigation(
    @StringRes val name: Int,
    val route: String,
    val drawableRes: ImageVector,
) {
    data object Cart : Navigation(R.string.navigation_cart, "cart", AppIcons.Cart)
    data object History : Navigation(R.string.navigation_history, "history", AppIcons.List)
    data object Statistics : Navigation(R.string.navigation_statistics, "statistics", AppIcons.Info)
}

I've tried to change dependencies, change debug to release mode, using code from Now in Android, nothing seems to work. I'm out of ideas.


Solution

  • It is a bug in 1.5.4 of androidx.compose.ui:ui-graphics library. Problem disappeared by using >= 1.6.0-alpha03 version.