Ped*_*ira 0 optimization android lazy-loading android-xml android-jetpack-compose
我正在为非常有限的硬件开发一个应用程序,并决定使用 jetpack compose。
当我需要显示卡片列表并且用于它的惰性行变得非常滞后时,问题就出现了。为了进行比较,我选择了一个带有 recyclerView 的示例项目,并用它来显示大致相同的卡片列表,并且滚动尽可能平滑。jetpack compose 本质上比 xml view 慢还是我做错了什么?
撰写代码(我无法准确分享我的代码,但可组合的卡片只是一张带有一些图像、图标和文本的卡片):
@Composable
fun mainComposable(){
...
cardList = remember{ arrayListOf(...) }
lazyList(cardList)
...
}
@Composable
fun lazyList(
cardList: List<CardContent>,
){
LazyRow(
horizontalArrangement = Arrangement.spacedBy(16.dp),
contentPadding = PaddingValues(horizontal = 32.dp)
) {
items(
items = cardList,
key = { it.id }) { item ->
CardComposable(
content = item
)
}
}
}
Run Code Online (Sandbox Code Playgroud)
我已经花了一些时间搜索,所以我发现了很多优化,比如在发布模式下运行,在 build.gradle 上将 minifyEnabled 和收缩资源设置为 true,在 gradle.properties 中将 android.enableR8.fullMode 设置为 true,使用 LazyRow 上的键他们有所帮助,但滚动仍然比带有 recyclerView 的等效 xml 视图应用程序慢。
编辑:添加了 CardComposable 代码
@Composable
fun CardComposable(
content: Content,
) {
Card(
shape = RoundedCornerShape(8.dp),
elevation = 1.dp,
modifier = Modifier
.width(216.dp)
.height(308.dp)
) {
Column {
Box(contentAlignment = Alignment.TopEnd) {
Image(
painter = painterResource(id = content.image),
modifier = Modifier
.width(216.dp)
.height(164.dp)
)
Box(
contentAlignment = Alignment.Center,
modifier = Modifier.padding(8.dp)
) {
Image(
painter = painterResource(id = R.drawable.button_background),
modifier = Modifier
.width(40.dp)
.height(40.dp)
)
Icon(
painter = painterResource(id = R.drawable.button),
modifier = Modifier
.width(16.dp)
.height(16.dp),
tint = GenericRedColor
)
}
}
Column(
modifier = Modifier
.padding(start = 16.dp)
) {
Row(verticalAlignment = Alignment.CenterVertically) {
Text(
text = content.Name,
maxLines = 2,
color = GenericBlackColor,
fontSize = 16.sp,
fontWeight = FontWeight(500),
overflow = TextOverflow.Ellipsis,
modifier = Modifier
.width(134.dp)
.padding(top = 16.dp)
)
Box(
contentAlignment = Alignment.Center,
modifier = Modifier.padding(start = 16.dp, top = 8.dp)
) {
Icon(
painter = painterResource(id = R.drawable.square_button),
modifier = Modifier
.width(32.dp)
.height(32.dp),
tint = GenericRedColor
)
Icon(
painter = painterResource(id = R.drawable.button_icon),
modifier = Modifier
.width(16.dp)
.height(16.dp),
tint = GenericWhiteColor
)
}
}
Text(
text = content.contentType,
color = GenericLightGrayColor2,
fontSize = 14.sp,
modifier = Modifier.padding(top = 8.dp)
)
Row(
horizontalArrangement = Arrangement.spacedBy(26.dp),
modifier = Modifier.padding(top = 24.dp)
) {
val iconModifier = Modifier
.padding(end = 4.dp)
.width(12.dp)
.height(12.dp)
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(
painter = painterResource(R.drawable.icon_1),
modifier = iconModifier,
tint = GenericLightGrayColor2
)
Text(
text = content.text_1,
fontSize = 14.sp,
color = GenericLightGrayColor2
)
Icon(
painter = painterResource(R.drawable.icon_2),
modifier = iconModifier,
tint = GenericLightGrayColor2
)
Text(
text = content.text2,
fontSize = 14.sp,
color = GenericLightGrayColor2
)
Icon(
painter = painterResource(R.drawable.icon_3),
modifier = iconModifier,
tint = GenericLightGrayColor2
)
Text(
text = content.text3,
fontSize = 14.sp,
color = GenericLightGrayColor2
)
}
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
Jetpack Compose 是一个单独的库,不包含在 Android 操作系统中。因此,库中的代码应该在第一次运行时进行即时 (JIT)编译。这使得它本质上比基于 Android View 的代码慢,后者是提前编译 (AOT) 的,并且二进制文件存储在设备的操作系统内。
将 Jetpack Compose 作为独立库的设计决策也有其优点。无论 Android 操作系统版本如何,它都可以更轻松地更新和使用不同版本的库,并实现 compose 和 android 版本之间的向后兼容性。
在 iOS 中,Swift 采用了另一种方法,Swift 二进制文件是提前编译并包含在操作系统中的。这是除了苹果的懒惰之外阻碍 iOS 向后兼容的主要原因之一。
关于 RecyclerView 和 LazyLists 之间的性能差异,LazyLists 的性能明显低于 RecyclerView。这有多种原因。我认为这主要是因为 Compose 是一个较新的库并且正在不断改进。LazyLists 早期版本的性能要差得多。在即将推出的 compose 版本中,性能将进一步提高。
目前,由于 Jetpack Compose 与基于 Android View 的代码具有互操作性,因此您可以在 Compose 中使用 RecyclerView,并且性能开销最小。使用AndroidView()Jetpack Compose 中的函数。
@Composable
fun MyView(data: State<List<Item>>) {
//This function enables Compose to interop with View based code.
AndroidView(
factory = { context ->
RecyclerView(context).apply {
layoutParams = ViewGroup.LayoutParams(MATCH_PARENT, WRAP_CONTENT)
layoutManager = LinearLayoutManager(context)
adapter = ItemListAdapter().also { it.submitList().value }
}
},
update = { recyclerView ->
//Callback that runs on each recomposition.
}
)
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2254 次 |
| 最近记录: |