[Android] Compose 3 项代码优化示例

107 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情

这是第一种情况的示例。

Box(
	modifier = Modifier.fillMaxSize(),
    contentAlignment = Alignment.Center
) {
	RgbSelector(
    	color = viewModel.curretColor,
        onColorClick = {
        	viewModel.changeViewColor(it)
        }
    )
}

这是一个使用频率很高的基础代码,是一个简单的应用,当点击红、绿、蓝三个按钮时,将矩形的颜色改变为对应的颜色。

但是,如果你像上面那样写代码,当你按下一个按钮时,接收效果的矩形和按钮将被重新组合为其余的按钮。在这种情况下,如果屏幕组成本身在性能关键应用程序中变得复杂和庞大,就会出现性能下降。

原因是下面的部分写成lambda表达式。这是因为在编译下面的代码时,Kotlin 中的 lambda 表达式被写成 Anonymous Class,而 Jetpack Compose 将其视为不稳定代码。(我认为这是因为仅当参数发生变化时才应重新组合可组合项,但不确定)

onColorClick = {
	viewModel.changeViewColor(it)
}

下面的方法并不一定正确的。

Box(
	modifier = Modifier.fillMaxSize(),
    contentAlignment = Alignment.Center
) {
	RgbSelector(
    	color = viewModel.curretColor,
        onColorClick = viewModel::changeViewColor
    )
}

,只有单击的按钮会受到影响,其余按钮不会重新组合。

这是第二种情况的示例。

data class TestUser(
	val id: String,
    val email: String,
    val username: String
)
@Composable
fun TestView(
	user: TestUser
) {
	Text(text = "你好! ${user.username}!")
}

上面的 TestUser 类显示了导入外部库或 API 并将其用作外部模块的情况。并编写一个简单的可组合函数,接收用户作为参数并输出用户名,如下面的代码所示。

即使在上述情况下,Jetpack Compose 在编译时也会将 User 类视为不稳定。

因此,可以通过在一个内部模块(TestView所属的模块)中创建一个Mapper Class来解决。

data class User(
	val id: String,
    val email: String,
    val username: String
)

fun TestUser.toUser(): User {
	return User(
    	id = id,
        email = email,
        username = username
    )
}

fun User.toTestUser(): TestUser {
	return TestUser(
    	id = id,
        email = email,
        username = username
    )
}

这是第三种情况的示例。

让我用文字简单地解释一下,没有代码。
假设应用程序在屏幕上显示三张面朝上的卡片,当单击洗牌按钮时,三张卡牌的位置随机切换。

创建名为 CustomGrid 的可组合项,如下所示。

CustomeGrid(
	...
) {
	...
    Row(
    	...
    ) {
    	// 1 ~ 3
    	RowCards.forEach { card ->
        	CardView(card = card)
    	}
    }
    ...
}

此处需要注意的重要一点是,单击“随机播放”按钮只会更改三张卡片的顺序,而不是卡片本身。(卡号、形状等)
因此,即使按下按钮,CardView也不需要重新组合。只需要更改行的排列。
如果您使用 LazyRow,它会处理它,但假设情况并非如此,如果您使用下面的方法,CardView 将不会重新组合,只会重新排列顺序。

Row(
    	...
    ) {
    	// 1 ~ 3
    	RowCards.forEach { card ->
        	key(card.num) {
            	CardView(card = card)
            }
    	}
    }

如果这样写代码,CardView只有在键值改变的时候才会重新组合。