최근 Stable로 올라온 Compose 1.2 버전에서movableContentOf
와 movableContentWithReceiverOf
라는 새로운 두 함수가 추가되었다.
기존에는 동일한 Content이라도 부모가 바뀌게 되면 기존의 Content 없애고 새로운 Content을 구성하는 형태로 동작하였다.
이제는 movableContentOf
을 사용하여 기존의 Content를 재구성 없이 그대로 이동시킬 수 있고, 재구성에 필요한 불필요한 비용 줄일 수 있다.
사용 방법은 mutableStateOf
와 동일하게 remember
로 감싸주면 되고 내부에 Content를 넣어주면 된다.
1. movableContentOf
@Composable
fun MovableContentTest() {
val boxs = remember {
listOf(
"A" to Color.Blue,
"B" to Color.DarkGray,
"C" to Color.Magenta,
"D" to Color.Green
).map { (text, color) ->
movableContentOf {
Log.d("two22", "movableContentOf $text")
Box(
modifier = Modifier
.padding(20.dp)
.size(80.dp)
.background(color, RoundedCornerShape(percent = 25)),
contentAlignment = Alignment.Center
) {
Text(
text = text,
fontSize = 40.sp
)
}
}
}
}
Column(horizontalAlignment = Alignment.CenterHorizontally) {
val position = remember { mutableStateListOf(0, 1, 2, 3) }
Button(onClick = {
position.shuffle()
}) {
Text("Shuffle")
}
Row {
boxs[position[0]]()
boxs[position[1]]()
}
Row {
boxs[position[2]]()
boxs[position[3]]()
}
}
}
movableContentOf
을 이용해서 4개의 box을 하나의 boxs 변수에 담았다.
그리고 생성될때마다 로그를 찍도록 하고, shuffle 이 될 때에는 다른 곳으로 이동하도록 만들었다.
로그를 확인하면 제일 초기 생성에서만 로그가 찍혔고, Content 가 이동되고 있을 때는 아무런 로그도 찍히지 않았다.
2. movableContentWithReceiverOf
movableContentWithReceiverOf
의 사용법은 movableContentOf
와 동일하고 추가로 사용 영역을 제한할 수 있다.
@Composable
fun MovableContentWithReceiverTest() {
val boxs = remember {
listOf(
"A" to Color.Blue,
"B" to Color.DarkGray,
"C" to Color.Magenta,
"D" to Color.Green
).map { (text, color) ->
movableContentWithReceiverOf<RowScope> {
Log.d("two22", "movableContentOf $text")
Box(
modifier = Modifier
.weight(1f)
.padding(20.dp)
.size(80.dp)
.background(color, RoundedCornerShape(percent = 25)),
contentAlignment = Alignment.Center
) {
...
}
}
}
}
...
}
movableContentOf
를 사용하던 곳을 movableContentWithReceiverOf
로 바꾸고,
RowScope
에서만 사용 가능하도록 제한을 걸었다.
RowScope
로 제한했기 때문에 RowScope
에 정의된 weight
함수를 호출할 수 있게 된다.
동일하게 로그를 찍어보면 이전과 다르게 로그가 계속해서 찍히는 걸 볼 수 있다.
movableContentWithReceiverOf
의 차이가 아닌 weight 함수를 호출했기 때문이다.
Content의 이동으로 인해 부모가 바뀌었고, 부모의 영향을 받는 weight 함수는 다시 실행될 필요가 있다.
movableContentWithReceiverOf
로 최적화를 하려면 부모 scope의 modifier 직접 사용하지 않고,
아래 방법을 사용하는게 좋다.
3. movableContentWithReceiverOf parameter
movableContentWithReceiverOf
는 인자로 최대 3개의 parameter를 넘길 수 있다
@Composable
fun MovableContentWithReceiverTest() {
val boxs = remember {
listOf(
...
).map { (text, color) ->
movableContentWithReceiverOf<RowScope, Modifier> { modifier ->
Log.d("two22", "movableContentOf $text")
Box(
modifier = modifier
.padding(20.dp)
.size(80.dp)
.background(color, RoundedCornerShape(percent = 25)),
contentAlignment = Alignment.Center
) {
...
}
}
}
}
Column(horizontalAlignment = Alignment.CenterHorizontally) {
...
Row {
boxs[position[0]](Modifier.weight(1f))
boxs[position[1]](Modifier.weight(1f))
}
Row {
boxs[position[2]](Modifier.weight(1f))
boxs[position[3]](Modifier.weight(1f))
}
}
}
위에 코드는 Modifier를 호출 paremeter에 담아서 넘겨주는 방식으로 작성한 코드이다.
이렇게 하면 부모가 변경되어도 Content를 재구성하지 않고 이동시키는 것이 가능하다.
Row {
boxs[position[0]](Modifier.weight(1f))
boxs[position[1]](Modifier.align(Alignment.CenterVertically))
}
Row {
boxs[position[2]](Modifier.background(Color.Black))
boxs[position[3]](Modifier.weight(1f))
}
대신 위에 처럼 Modifier 가 각각 다르고 이걸로 인해 다시 그려져야 하는 뷰들은 재구성이 진행된다.
'안드로이드' 카테고리의 다른 글
Android - Compose 1.3 PullRefresh (0) | 2022.11.01 |
---|---|
Android - Compose 1.2 바뀐 것 (0) | 2022.08.11 |
Compose 1.1 정리 (0) | 2022.02.16 |
compose 넣은 xml 불러오면 에러날 때 (2) | 2021.06.22 |
오픈소스 라이선스 만들기 (0) | 2021.02.23 |