앱 상태로 UI에 표시할 항목에 관한 설명이 제공되고,
이벤트라는 메커니즘을 통해 상태가 변경되고 UI도 변경됩니다.
💡 핵심 아이디어: 상태는 존재하고 이벤트는 발생한다.
💡 Compose가 추적할 상태를 알아야 함 > 그래야 업데이트를 받을 때 리컴포지션을 예약할 수 있음
- 컴포지션 : 컴포저블을 실행할 때 Jetpack Compose에서 빌드한 UI에 관한 설명입니다.
- 초기 컴포지션: 처음 컴포저블을 실행하여 컴포지션을 만듭니다.
- 리컴포지션: 데이터가 변경될 때 컴포지션을 업데이트하기 위해 컴포저블을 다시 실행하는 것
remember
rememberSavable
활동 또는 프로세스가 다시 생성된 이후
rememberSaveable을 사용하여 UI 상태를 복원합니다.
여러 리컴포지션 간에 상태를 유지하는 것 외에도
rememberSaveable은 활동 및
프로세스 재생성 전반에 걸쳐서도 상태를 유지합니다.
remember
를 사용하여 객체를 저장하는 컴포저블에는 내부 상태가 포함되어 있는 컴포저블💡 상태 호이스팅 패턴
두 개의 매개변수(파라미터)로 바꾸는 것
- value: T - UI에 표시해야 할 현재 값(상태), 상태는 내림(🔻)
- onValueChange: (T) -> Unit - 값을 변경하도록 요청하는 이벤트, 위임할 액션(🔺)
💡 단방향 데이터 흐름(UDF)
- 상태가 내려가고 이벤트가 올라가는 패턴
- 단방향 데이터 흐름(UDF)
- 호이스팅을 이용한 Compose 구현하는 방법
핵심 사항
상태를 끌어올릴 때 상태의 이동 위치를 쉽게 파악할 수 있는 세 가지 규칙
1. 상태는 적어도 그 상태를 사용하는 모든 컴포저블의 가장 낮은 공통 상위 요소로 끌어올려야 한다. (읽기)
2. 상태는 최소한 변경될 수 있는 가장 높은 수준으로 끌어올려야 한다. (쓰기)
3. 두 상태가 동일한 이벤트에 대한 응답으로 변경되는 경우 두 상태는 동일한 수준으로 끌어올려야 합니다.
상태를 충분히 높은 수준으로 끌어올리지 않으면 단방향 데이터 흐름을 따르거나 어렵거나 불가능할 수 있다.
comp
: @Composeable
함수 설정prev
: 구성 가능한 @Preview
함수 만들기paddp
: dp에 padding
수정자 추가weight
: weight
수정자 추가W
, WR
, WC
: 현재 컴포저블을 Box
, Row
또는 Column
컨테이너로 둘러싸기val listState = rememberLazyListState()
mutableStateListOf
API 사용하여 목록을 만들 수 있다.// 💩 Don't do this!
// 리컴포지션 UI 성능 최적화 X
val list = remember { mutableStateListOf<WellnessTask>() }
list.addAll(getWellnessTasks())
// ✅ Do this instead.
// 단일 작업으로 초기값을 사용하여 목록 만든 후 remember 함수에 전달
val list = remember {
mutableStateListOf<WellnessTask>().apply {
addAll(getWellnessTasks())
}
}
변경 가능한 목록에서 데이트 세트가 변경될 때
--> 위치를 변경하는 항목은 기억된 상태를 잃음
--> 데이터들이 삭제 추가 됐을 때 기본 상태를 저장할 시 위치로 저장함
--> 따라서 데이트 크기가 변경 될 때 문제 발생
items
메서드는 key
매개변수를 수신.
--> 모든 데이터를 리컴포지션 할 필요 없어짐
--> 단 키는 반드시 유니크 해야함 > 현실적으로 어려울 수 있음 고려
--> 예) items(key = {task -> task.id})
viewModel()
함수를 호출하여 컴포저블에서 이 viewModel에 엑세스할 수 있음. > implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.4.1"
ViewModel은 탐색 그래프의 활동이나 프래그먼트, 대상에서 호출되는 루트 컴포저블에 가까운 화면 수준 컴포저블에서 사용하는 것이 좋습니다. ViewModel은 다른 컴포저블로 전달하면 안 됩니다. 대신 필요한 데이터와 필수 로직을 실행하는 함수만 매개변수로 전달해야 합니다.
자세한 내용은 ViewModel 및 상태 홀더 섹션과 Compose 및 기타 라이브러리 문서를 참고하세요.
// 추적 안 되는 클래스
data class WellnessTask(
val id: Int,
val label: String,
var checked: Boolean = false // Compose 에서 해당 값을 추적이 안 됨
)
개선1 - MutableState로 속성넣기
data class WellnessTask(
val id: Int,
val label: String,
val checked: MutableState<Boolean> = mutableStateOf(false) // Compose 에서 해당 값 추적 가능 함
)
개선2 - 위임 속성 활용
class WellnessTask(
val id: Int,
val label: String,
initialChecked: Boolean = false
) {
var checked by mutableStateOf(initialChecked)
}