【问题标题】:Jetpack compoes lazycolumn skipping frames (lagging)Jetpack composelazycolumn 跳帧(滞后)
【发布时间】:2021-07-26 17:33:18
【问题描述】:

您好,我正在尝试实现帖子列表的lazycolumn,我在模拟器 api 21 和 29 上对其进行了测试,它在 api 29 上看起来有点流畅,当我在其上进行测试时它有点滞后它是滞后的物理设备,它看起来像是在跳帧什么的......

我试图删除一些使用imageVector 的视图,看看是否是问题所在,并且仍然是同样的问题。

这是我的可组合视图:

@Composable
fun HomePostView(
    category: String,
    imagesUrl: List<String> = listOf(imageHolder),
    doctorProfileImage: String = imageUrl,
    title: String,
    subTitle: String
) {


    Card(
        shape = PostCardShape.large, modifier = Modifier
            .padding(horizontal = 3.dp)
            .fillMaxWidth()
    ) {

        Column {

            PostTopView(
                category = category,
                onOptionsClicked = { /*TODO option click*/ },
                onBookmarkClicked = {/*TODO bookmark click*/ })

            CoilImage(
                data = imagesUrl[0],
                fadeIn = true,
                contentDescription = "post_image",
                modifier = Modifier
                    .fillMaxWidth()
                    .requiredHeight(190.dp)
                    .padding(horizontal = contentPadding),
                contentScale = ContentScale.Crop
            )

            Spacer(modifier = Modifier.height(10.dp))

            PostDoctorContent(
                doctorProfileImage = doctorProfileImage,
                title = title,
                subTitle = subTitle
            )
            Spacer(modifier = Modifier.height(contentPadding))

            PostBottomView(likesCount = 293, commentsCount = 22)

            Spacer(modifier = Modifier.height(contentPadding))

        }


    }
    Spacer(modifier = Modifier.height(10.dp))


}


@Composable
private fun PostDoctorContent(doctorProfileImage: String, title: String, subTitle: String) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(horizontal = contentPadding)
    ) {

        CoilImage(data = doctorProfileImage,
            contentScale = ContentScale.Crop,
            contentDescription = null,
            fadeIn = true,
            modifier = Modifier
                .size(30.dp)
                .clip(CircleShape)
                .clickable {
                    /*Todo on doctor profile clicked*/
                })


        Column {
            Text(
                text = title, fontSize = 14.sp, maxLines = 1,
                overflow = TextOverflow.Ellipsis,
                modifier = Modifier.padding(horizontal = contentPadding)
            )

            Text(
                text = subTitle,
                fontSize = 11.sp,
                color = LightTextColor,
                maxLines = 2,
                overflow = TextOverflow.Ellipsis,
                modifier = Modifier.padding(horizontal = contentPadding)
            )
        }
    }


}

@Composable
private fun PostBottomView(likesCount: Long, commentsCount: Long) {
    Row(
        modifier = Modifier.padding(horizontal = contentPadding),
        verticalAlignment = Alignment.CenterVertically
    ) {

        Row(
            Modifier
                .clip(RoundedCornerShape(50))
                .clickable { /*Todo on like clicked*/ }
                .padding(5.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {
            Icon(
                imageVector = ImageVector.vectorResource(id = R.drawable.ic_heart),
                contentDescription = "Like"
            )
            Spacer(modifier = Modifier.width(5.dp))
            Text(text = likesCount.toString(), fontSize = 9.sp)
        }
        Spacer(Modifier.width(20.dp))

        Row(
            Modifier
                .clip(RoundedCornerShape(50))
                .clickable { /*Todo on comment clicked*/ }
                .padding(5.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {
            Icon(
                imageVector = ImageVector.vectorResource(id = R.drawable.ic_comment),
                contentDescription = "Comment"
            )
            Spacer(modifier = Modifier.width(5.dp))
            Text(text = commentsCount.toString(), fontSize = 9.sp)
        }


    }
}

@Composable
private fun PostTopView(
    category: String,
    onOptionsClicked: () -> Unit,
    onBookmarkClicked: () -> Unit
) {
    Row(
        modifier = Modifier.fillMaxWidth(),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.SpaceBetween
    ) {

        Row(verticalAlignment = Alignment.CenterVertically) {
            IconButton(onClick = onOptionsClicked) {
                Icon(
                    imageVector = ImageVector.vectorResource(id = R.drawable.ic_threedots),
                    contentDescription = "Options",
                    tint = Color.Unspecified
                )
            }

            Text(text = category, fontSize = 16.sp, color = LightTextColor)

        }

        IconButton(onClick = onBookmarkClicked) {
            Icon(
                imageVector = ImageVector.vectorResource(id = R.drawable.ic_bookmark),
                contentDescription = "Bookmark"
            )
        }

    }
}

和lazyColumn:

LazyColumn(contentPadding = paddingValues , state = state ) {
    item {
        Spacer(modifier = Modifier.height(10.dp))

        DoctorsList(
            viewModel.doctorListData.value,
            onCardClicked = {})
    }
    items(30) {  post ->
        HomePostView(
            category = "Public Health ",
            title = "Food Importance",
            subTitle = "you should eat every day it's healthy and important for you, and drink water every 2 hours and what you should do is you should run every day for an hour"
        )

    }
}

注意:我仍然没有使用视图模型,我只是用假数据测试视图

【问题讨论】:

  • 尝试在items(30, keys = { it } ) 上使用key 使更流畅,但是是的,android compose 自测试版以来仍然不利于性能
  • 我们正在做出重大改变,希望能尽快落地,从而改善这一点。当帧之间的时间允许时,首先LazyList 现在将预先组合行。其次,行现在将在行之间共享布局信息,类似于RecyclerView。这仍在积极开发中,因此可能会发生其他变化。
  • @chuckj Compose 现在稳定了。为什么 LazyColumn 的性能还这么差?它至少在 Google 的问题列表中排名靠前吗?
  • 这就像一个被低估的问题。怎么没人问这里发生了什么?
  • Compose 是一个外部库,在开发过程中将 JIT 直到部署设备上出现配置文件。这对于任何外部库都是正常的。为了更好地了解它在配置文件生成后的执行情况,请在启用 R8 的情况下运行发布版本,并确保您在设备上手动运行 AOT。

标签: android kotlin android-jetpack android-jetpack-compose


【解决方案1】:

这可能不适用于其他任何人,但在早期版本 (1.0.0-beta01) 上,当我切换时,我看到性能有了非常大的提升

lazy(items) { item ->
    ...
}

items.forEach { item ->
    lazy {
        ...
    }
}

我不知道为什么,我不确定在以后的版本中是否仍然如此,但值得检查。因此,对于问题中给出的示例,这将意味着改变

items(30) {
    ...
}

repeat(30) {
    item { 
        ...
    }
}

【讨论】:

    【解决方案2】:

    TLDR:确保新的 LazyColumn 组合元素不在 RelativeLayout 或 LinearLayout 中。

    经过一番调查,对我们来说这个问题的解决方案是 LazyColumn 受到约束的视图。

    我们的项目结合使用 Jetpack Compose 和较旧的 XML 布局文件。我们的新 compose 元素嵌入在现有 XML 文件的 RelativeLayout 中。这就是问题所在。 compose 元素将被赋予整个屏幕,然后调用 compose 元素的 onMeasure 函数来重新配置视图并添加我们的底部导航栏......这个 onMeasure 被一遍又一遍地调用,这也是在当高度发生变化时,重新测量的 LazyColumn 正在丢弃缓存。

    我们的解决方案是更改包含新 compose 元素和底部导航栏的 RelativeLayout,并将其替换为 ConstraintLayout。这可以防止 onMeasure 被调用两次以上,并大大提高了性能。

    【讨论】:

    • 对我来说,LinearLayout 比 RelativeLayout 性能要好得多。
    【解决方案3】:

    尝试在关闭调试日志的情况下构建发布版本。应该可以正常工作。

    【讨论】:

      【解决方案4】:

      好的,到目前为止,我知道 API 在性能方面存在问题......但我发现的是这个

      实际上,就我而言,我只是加载了 2980*3750 像素的图像。我只是通过其他一些工具将我的资源压缩到更短的像素

      现在不存在滞后...

      【讨论】:

        【解决方案5】:

        就我而言,在我将ComposeView 的高度设置为特定值后,它会使LazyColumn 滚动平滑。
        因此,我创建了一个XML 文件,如

        <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
        
            <androidx.compose.ui.platform.ComposeView
                android:id="@+id/compose"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
        
        </FrameLayout>
        

        Fragment

        override fun onViewCreated(view: View, savedInstanceState: Bundle ? ) {
            super.onViewCreated(view, savedInstanceState)
            view.doOnLayout {
                compose.layoutParams.height = view.height
                compose.requestLayout()
            }
        }
        

        我知道ComposeView 的高度已经match_parent,所以在Fragment 上再次设置它的高度似乎没用。但是,如果不设置高度,LazyColumn 在滚动时会滞后。
        我不确定它是否适用于所有设备,但适用于我的 PixelXiomi

        【讨论】:

          【解决方案6】:

          如果您在项目中使用 JPG 或 PNG,请检查它们的大小,较大的图像会在低端设备上导致很多滞后问题。 我在使用简单的 LazyColumn 列表时遇到了同样的问题,结果发现我使用的是大小超过 2MB 的 JPG。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-06-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-12-31
            • 1970-01-01
            • 2018-05-31
            相关资源
            最近更新 更多