2022년 4월 15일 금요일

[안드로이드] Compose 2 - 생명주기

 

목차

  1. Compose 시작
  2. Compose의 생명주기
  3. Compose에서의 상태(State)
  4. 렌더링 수행 과정
  5. 부수효과(Side-Effect)
  6. 시맨틱(Semantics)
  7. 아키텍쳐 레이어
  8. 로컬 범위지정(Scope) 데이터

Compose 생명주기

개요



  1. 최초 1회 컴포지션
  2. (변경사항이 있는 경우) 리컴포지션 (0~n번)
  3. 컴포지션 해제/종료

컴포지션(Composition)

  • Composable 함수를 트리 구조로 변환하는 작업. 이렇게 변환된 트리구조는 내부적으로 인스턴스화 되며, 이 인스턴스로 Compose 프레임워크가 화면에 렌더링을 수행
  • 컴포지션은 Composable 함수가 처음 호출될 때 수행
  • 컴포지션은 Composable 함수가 호출되는 위치마다 각각 수행(여러개의 인스턴스가 생성됨)
    • Compose 컴파일러가 Composable 함수가 호출되는 위치(Call Site)와 호출순서를 Key로 하여, 컴포지션 인스턴스를 관리

컴포지션 예시

@Composable
fun MyComposable() {
    Column {
        Text("Hello")
        Text("World")
    }
}

// 최초 호출시 Composition 수행됨
MyComposable()


리컴포지션(Recomposition)

  • 컴포지션으로 생성된 트리 인스턴스를 변경하여 트리 인스턴스를 다시 구성하는 작업.
    • 변경이 필요한 경우, 기존 인스턴스를 재사용하지 않고 새로운 인스턴스를 생성
    • 트리의 모든 인스턴스를 재생성하지 않고, 변경이 있는 인스턴스만 재생성
  • 리컴포지션의 수행 시점
    • 인자가 있는 Composable 함수에서, 인자가 변경되어 함수가 다시 호출되었을 때
    • 함수 내부에서 State객체를 사용하는 경우, State객체의 값이 변경되었을 때

리컴포지션 예시 - 유지되는 인스턴스와 변경된 인스턴스

@Composable
fun MyComposable(text: String) {
    Column {
        Text("Hello")
        Text(text)
    }
}

// MyComposable()을 파라미터 바꿔서 두번 호출
val list = listOf("Kotlin", "Android")
for (text in list) {
    MyComposable(text)
}



스마트 리컴포지션 (Smart Recomposition)

  • 스마트 리컴포지션 : Composable함수가 호출될 때마다 무조건 리컴포지션을 수행하면 인스턴스가 재생성되어 비효율적이므로, 변경이 필요한 경우에만 리컴포지션을 수행하는 것
  • 리컴포지션을 건너뛰는 경우 (모든 조건을 만족해야 함)
    • 호출 위치/순서가 변경되지 않음.
    • 파라미터가 Stable 타입
    • 파라미터의 값이 변경되지 않음. (equals() 값이 동일)

Stable 타입

  • 다음 특성을 만족하는 데이터타입으로, Compose 컴파일러는 @Stable 어노테이션을 붙은 클래스/인터페이스를 stable한 타입으로 인식
    • equals() 메서드로 두 인스턴스의 동일성이 항상 보장됨
    • public 프로퍼티가 변경되면, 컴포지션이 해당 변경사항을 알림받을 수 있어야 함.
    • 모든 public 프로퍼티가 stable 타입
@Stable
interface UiState<T : Result<T>> {
    val value: T?
    val exception: Throwable?

    val hasError: Boolean
        get() = exception != null
}
  • @Stable 어노테이션 없어도 stable 타입으로 인식되는 경우
    • 모든 primitive 타입 : Boolean, Int, Long, Float, Char 등..
    • 문자열 (String)
    • 모든 함수 유형(람다)

Composable의 별도 값을 식별자로 사용하기 - key() 함수

  • Compose 컴파일러는 Composable 함수의 호출순서가 달라지면 리컴포지션을 수행함
@Composable
fun MoviesScreen(movies: List<Movie>) {
    Column {
        // movies 리스트의 정렬을 바꾼다면, 기존의 호출순서와 달라지므로 MovieOverview()가 리컴포지션을 수행
        for (movie in movies) {
            MovieOverview(movie)
        }
    }
}



  • Compose 컴파일러가 호출순서 대신에 별도의 식별자를 이용하여 컴포지션을 관리하도록, key() Composable 함수를 지원. 식별자로 사용할 값을 key() 함수의 첫번째 인자로 전달한다.
@Composable
fun MoviesScreen(movies: List<Movie>) {
    Column {
        // movies 리스트의 정렬을 바꾼다면, 기존의 호출순서와 달라지므로 MovieOverview()가 리컴포지션을 수행
        for (movie in movies) {
            // movie 객체의 식별자(id)를 인자로 넘겨준다.
            key (movie.id) {
                MovieOverview(movie)
            }
        }
    }
}



댓글 없음:

댓글 쓰기