Compose Accompanist Pager 中的 TabRow/Tab 重组问题

jan*_*sad 6 android kotlin android-jetpack-compose jetpack-compose-accompanist compose-recomposition

我试图在 Jetpack compose 中创建一个示例选项卡视图,因此结构将类似于在父选项卡行内部,我们正在迭代选项卡标题并创建选项卡可组合项。

更精确的代码将是这样的。

@OptIn(ExperimentalPagerApi::class)
@Composable
private fun MainApp() {
    Scaffold(
        topBar = {
            TopAppBar(
                title = { Text(stringResource(R.string.app_name)) },
                backgroundColor = MaterialTheme.colors.surface
            )
        },
        modifier = Modifier.fillMaxSize()
    ) { padding ->
        Column(Modifier.fillMaxSize().padding(padding)) {
            val pagerState = rememberPagerState()
            val coroutineScope = rememberCoroutineScope()
            val tabContents = listOf(
                "Home" to Icons.Filled.Home,
                "Search" to Icons.Filled.Search,
                "Settings" to Icons.Filled.Settings
            )
            HorizontalPager(
                count = tabContents.size,
                state = pagerState,
                contentPadding = PaddingValues(horizontal = 32.dp),
                modifier = Modifier
                    .weight(1f)
                    .fillMaxWidth()
            ) { page ->
                PagerSampleItem(
                    page = page
                )
            }

            TabRow(
                selectedTabIndex = pagerState.currentPage,
                backgroundColor = MaterialTheme.colors.surface,
                contentColor = MaterialTheme.colors.onSurface,
                indicator = { tabPositions ->
                    TabRowDefaults.Indicator(
                        Modifier
                            .pagerTabIndicatorOffset(pagerState, tabPositions)
                            .height(4.dp)
                            .background(
                                color = Color.Green,
                                shape = RectangleShape
                            )
                    )
                }
            ) {
                tabContents.forEachIndexed { index, pair: Pair<String, ImageVector> ->
                    Tab(
                        selected = pagerState.currentPage == index,
                        selectedContentColor = Color.Green,
                        unselectedContentColor = Color.Gray,
                        onClick = {
                            coroutineScope.launch {
                                pagerState.animateScrollToPage(index)
                            }
                        },
                        text = { Text(text = pair.first) },
                        icon = { Icon(imageVector = pair.second, contentDescription = null) }
                    )
                }
            }
        }
    }
}

@Composable
internal fun PagerSampleItem(
    page: Int
) {
    // Displays the page index
    Text(
        text = page.toString(),
        modifier = Modifier
            .padding(16.dp)
            .background(MaterialTheme.colors.surface, RoundedCornerShape(4.dp))
            .sizeIn(minWidth = 40.dp, minHeight = 40.dp)
            .padding(8.dp)
            .wrapContentSize(Alignment.Center)
    )
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,每当我们单击选项卡项时,内部内容都会以奇怪的方式重新组合。我无法理解为什么会发生这种情况。

我在下面附上了重组计数的图像,也请看一下,如果你们能帮助我更多地理解这一点,对于未来的开发人员来说,那就太好了。

这个阶段有两个问题需要解决

  1. 当视图变得更加复杂时,是否会产生任何性能问题
  2. 如何解决这个重组问题

多谢。

在此输入图像描述

z.g*_*g.y 2

\n

\xe2\x80\xa6 每当我们单击选项卡项时,\ninner 内容就会以奇怪的方式重新组合。我无法理解为什么会发生......

\n
\n

很难确定这个“怪异”是什么,您在这里提到的可组合项中可能有一些东西。

\n

您也没有指定 API 是什么,所以我复制并粘贴了您的代码和集成伴奏视图寻呼机,然后我能够运行它,尽管不是Android Studio带有re-composition count运行。

\n

由于您只关心API 的参数Text和参数,所以我认为这是您无法控制的。我怀疑你得到这些重组计数的原因是因为你的Iconanimatingpage

\n
coroutineScope.launch {\n       pagerState.animateScrollToPage(index)\n}\n
Run Code Online (Sandbox Code Playgroud)\n

虽然无法在Android Studio具有该re-composition功能的另一个版本上尝试此操作,但我认为(尽管我不确定)滚动到另一个page 没有 animation该功能的版本会产生更少的重新组合计数。

\n
coroutineScope.launch {\n      pagerState.scrollToPage(index)\n}\n
Run Code Online (Sandbox Code Playgroud)\n

如果它仍然困扰你,最好的做法是直接询问他们,尽管我个人不会太关心这一点,因为它们是公认的 API 的一部分,而且它只是TextIcon动画多次重新组合, IMO也很好。

\n

现在,如果您对PagerSampleItem稳定性有一些担忧(您可以完全控制),根据提供的代码和屏幕截图,我认为您的情况很好。

\n

实际上,本文建议了一个功能来检查 的稳定性composable,我运行它并得到了这份报告。

\n
restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun PagerSampleItem(\n  stable page: Int\n)\n
Run Code Online (Sandbox Code Playgroud)\n

有关此报告的所有内容都在我链接的文章中。

\n

另外,您的TextIcon正在使用String和 ,ImageVector它分别是稳定和不可变的(由 @Immutable 标记)。

\n

所以TLDR,我认为你的代码很好,你的代码PagerSampleItem不在re-composing屏幕截图中。

\n