我编写了一些显示图像和视频的代码。我正在使用 viewModel,但在下面的代码中,即使数据没有变化,可组合性也会进行不必要的重组。它还会导致其子可组合项的重组时间与
MediaScreenBody()
的计数相同甚至更多。我尝试了很多方法,例如将 by 与collectAsState一起使用,但这些方法甚至导致了 10 倍的重组。第一次启动应用程序时,每个可组合项只有一个组合。然后如果我与应用程序交互,例如滑动或滚动,然后它也会重新组合 MediaSceenBpody()
及其子内容。由于重组,它还会导致滚动和滑动的滞后行为。我做了一些研究,发现 pagerState 可能会导致此问题。我尝试将 pagerState 设置为不同的数字,并且重组也更改为该数字。但请记住,有时它会导致更多的问题。那里没有必要只重组 pageState 的数量。我分享这个仅供大家参考。MediaSceenBpody()
编辑-
因为有很多关于不将状态或 viemodel 作为参数传递的建议。我尝试在使用 HorizontalPager 的 @Composable
fun MediaScreen(onMediaItemClick: () -> Unit) {
val mediaViewModel: MediaViewModel = viewModel(
factory = MediaViewModel.Factory
)
val photoUIState = mediaViewModel.photoUIState.collectAsState()
val videoUIState = mediaViewModel.videoUIState.collectAsState()
ScreenContent(
mediaViewModel = mediaViewModel,
photoUIState = photoUIState,
videoUIState = videoUIState,
onMediaItemClick = onMediaItemClick
)
}
@Composable
fun ScreenContent(
modifier: Modifier = Modifier,
mediaViewModel: MediaViewModel,
photoUIState: State<PhotoUIState>,
videoUIState: State<VideoUIState>,
onMediaItemClick: () -> Unit
) {
val topBarScrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
Scaffold(
modifier = modifier
.nestedScroll(topBarScrollBehavior.nestedScrollConnection),
topBar = {
TopAppBarContent(topBarScrollBehavior)
}
) { contentPadding ->
MediaScreenBody(
contentPadding = contentPadding,
mediaViewModel = mediaViewModel,
photoUIState = photoUIState,
videoUIState = videoUIState,
onMediaItemClick = onMediaItemClick
)
}
}
@Composable
fun TopAppBarContent(scrollBehavior: TopAppBarScrollBehavior? = null) {
TopAppBar(
title = {
Text(
text = stringResource(id = R.string.app_name)
)
},
colors = TopAppBarDefaults.topAppBarColors(
containerColor = if (isSystemInDarkTheme()) cs_theme_dark_topBar else cs_theme_light_topBar,
titleContentColor = Color.White
),
scrollBehavior = scrollBehavior
)
}
@Composable
fun MediaScreenBody(
modifier: Modifier = Modifier,
mediaViewModel: MediaViewModel,
contentPadding: PaddingValues,
photoUIState: State<PhotoUIState>,
videoUIState: State<VideoUIState>,
onMediaItemClick: () -> Unit,
) {
val pagerState = rememberPagerState {
3
}
var selectedTabIndex by rememberSaveable {
mutableIntStateOf(0)
}
Column(
modifier = Modifier
.padding(contentPadding)
.fillMaxSize()
) {
TabRow(
selectedTabIndex = selectedTabIndex,
containerColor = if (isSystemInDarkTheme()) cs_theme_dark_topBar else cs_theme_light_topBar,
contentColor = Color.White
) {
tabs.forEachIndexed { index, tabData ->
Tab(
selected = index == selectedTabIndex,
onClick = { selectedTabIndex = index },
text = { Text(text = tabData.title) }
)
}
}
HorizontalPager(
modifier = modifier.fillMaxSize(),
state = pagerState
) { currentPage ->
when (currentPage) {
0 -> {
when (photoUIState.value.mediaPhotos) {
is PhotoLoadingState.Loading -> LoadingScreen()
is PhotoLoadingState.Success -> SuccessScreen(
mediaList = (photoUIState.value.mediaPhotos as PhotoLoadingState.Success).photos,
onDownloadClick = {
val isSaved = mediaViewModel.saveMedia(it)
},
onMediaItemClick = onMediaItemClick
)
is PhotoLoadingState.Error -> ErrorScreen(onRetry = { mediaViewModel.loadPhotos() })
}
}
1 -> {
when (videoUIState.value.mediaVideos) {
is VideoLoadingState.Loading -> LoadingScreen()
is VideoLoadingState.Success -> SuccessScreen(
mediaList = (videoUIState.value.mediaVideos as VideoLoadingState.Success).videos,
onDownloadClick = {},
onMediaItemClick = onMediaItemClick
)
is VideoLoadingState.Error -> ErrorScreen(onRetry = { mediaViewModel.loadVideos() })
}
}
else -> {
val context = LocalContext.current
Button(onClick = {
Toast.makeText(
context,
"I'm working m third pager",
Toast.LENGTH_LONG
).show()
}) {
Text(text = "Hello")
}
}
}
}
}
}
中直接调用它。但当内容滚动时,它会导致超过 40-50 次重新合成,情况变得更糟。这就是我尝试将代码移动到
MediaScreenBody()
-MediaScreenBody()
切勿将视图模型传递给您的子可组合项。有一个回调来暗示事件并在该回调中使用您的视图模型。
val mediaViewModel: MediaViewModel = viewModel(
factory = MediaViewModel.Factory
)
val photoUIState = mediaViewModel.photoUIState.collectAsState()
val videoUIState = mediaViewModel.videoUIState.collectAsState()
您可以使用最后两个回调再次从视图模型加载。
val onClickLambda = Remember
Unit> { { // 视图模型访问 } }<() ->@Composable fun Test() { Button(onClick = onClickLambda) {} }
,最终已被修复
并发布于
fun MediaScreenBody(
modifier: Modifier = Modifier,
contentPadding: PaddingValues,
onMediaItemClick: () -> Unit,
onPhotoError: () -> Unit,
onVideoError: () -> Unit
)
请参阅发行说明