Jetpack Compose의 수명 주기   Android Jetpack의 구성요소

수명 주기 인식 구성요소는 호스트 활동의 수명 주기 상태 변경에 따라 작업을 실행합니다. androidx.lifecycle.compose 아티팩트는 화면을 벗어나거나 애플리케이션이 백그라운드로 전환될 때 리소스를 자동으로 정리하는 전용 API를 제공합니다.

주요 API에는 다음이 포함됩니다.

이러한 통합은 Compose 계층 구조 내에서 수명 주기를 관리하는 편리한 후크를 제공합니다. 이 문서에서는 앱에서 이를 사용하는 방법을 설명합니다.

흐름을 사용하여 수명 주기 상태 수집

Lifecycle은 현재 Lifecycle.State를 Kotlin StateFlow로 제공하는 currentStateFlow 속성을 노출합니다. 이 FlowState로 수집할 수 있습니다. 이렇게 하면 앱이 컴포지션 중에 Lifecycle의 변경사항을 읽을 수 있습니다.

val lifecycleOwner = LocalLifecycleOwner.current
val stateFlow = lifecycleOwner.lifecycle.currentStateFlow

val currentLifecycleState by stateFlow.collectAsState()

앞의 예시는 lifecycle-common 모듈을 사용하여 액세스할 수 있습니다. currentStateAsState() 메서드는 lifecycle-runtime-compose 모듈에서 사용할 수 있으며 한 줄로 현재 Lifecycle 상태를 편리하게 읽을 수 있습니다. 다음 예를 참고하세요.

val lifecycleOwner = LocalLifecycleOwner.current
val currentLifecycleState = lifecycleOwner.lifecycle.currentStateAsState()

수명 주기 이벤트에서 코드 실행

DefaultLifecycleObserver를 구현하는 별도의 클래스를 만들고 수명 주기에 수동으로 추가하는 대신 특정 효과를 사용하여 수명 주기 로직을 인라인으로 선언할 수 있습니다. LifecycleEffects를 사용하면 컴포지션 내에서 특정 Lifecycle.Event가 직접 발생할 때 블록을 실행할 수 있습니다.

LifecycleEventEffect

특정 이벤트가 발생할 때 코드 블록을 실행하려면 LifecycleEventEffect를 사용합니다. 성공도 즉각적인 결과도 필요하지 않은 로깅이나 분석과 같은 일회성 이벤트에 가장 적합합니다.

@Composable
fun AnalyticsTracker(screenName: String) {
    // Log an event when the app receives ON_RESUME (e.g. comes to foreground)
    LifecycleEventEffect(Lifecycle.Event.ON_RESUME) {
        Analytics.logView(screenName)
    }
}

LifecycleStartEffect

앱이 시작(표시)되는 동안 실행되고 앱이 중지 (백그라운드)될 때 정리해야 하는 페어링된 시작/중지 작업에는 LifecycleStartEffect를 사용합니다.

다른 Compose 효과 (예: LaunchedEffect)와 마찬가지로 LifecycleStartEffect는 키를 허용합니다. 키가 변경되면 블록이 다시 실행됩니다.

Lifecycle.Event.ON_STOP 이벤트가 발생하거나 효과가 컴포지션을 종료하면 onStopOrDispose 블록이 실행되어 시작 블록의 일부였던 모든 작업을 정리합니다.

@Composable
fun LocationMonitor(locationManager: LocationManager) {
    // Starts monitoring when ON_START is dispatched
    // Stops monitoring when ON_STOP is dispatched
    //   (or the composable leaves the screen)
    LifecycleStartEffect(locationManager) {
        val listener = LocationListener { location ->
            /* update UI */
        }
        locationManager.requestLocationUpdates(listener)
        // The cleanup block automatically runs on ON_STOP or on disposal
        onStopOrDispose {
            locationManager.removeUpdates(listener)
        }
    }
}

다른 유형의 부수 효과에 관한 자세한 내용은 Compose의 부수 효과를 참고하세요.

LifecycleResumeEffect

LifecycleResumeEffectLifecycleStartEffect와 동일한 방식으로 작동하지만 대신 Lifecycle.Event.ON_RESUME 이벤트에 연결됩니다. 또한 ON_PAUSE이 디스패치되거나 컴포저블이 화면을 벗어날 때 정리 작업을 실행하는 onPauseOrDispose 블록도 제공합니다.

이 API는 사용자가 앱과 상호작용할 때만 활성화되어야 하는 리소스(예: 카메라 또는 애니메이션)에 유용합니다.

@Composable
fun CameraPreview(cameraController: CameraController) {
    LifecycleResumeEffect(cameraController) {
        cameraController.startPreview()

        onPauseOrDispose {
            cameraController.stopPreview()
        }
    }
}

LifecycleOwner 액세스

Compose에서는 LifecycleOwnerLocalLifecycleOwner이라는 CompositionLocal을 통해 암시적으로 제공됩니다. 기본적으로 음악작품 계층 구조의 루트 호스트가 이 소유자를 제공합니다.

val lifecycleOwner = LocalLifecycleOwner.current

많은 앱에서 이 기본 소유자를 검사하거나 수명 주기 인식 효과에 전달하는 것으로 충분합니다. 하지만 맞춤 탐색 또는 복잡한 레이아웃의 경우 수명 주기 상태를 UI의 특정 섹션으로 범위 지정하기 위해 자체 LifecycleOwner를 만드는 것이 좋습니다. 예를 들어 탐색 라이브러리 (예: Navigation 3)는 각 개별 화면에 자체 수명 주기를 제공하기 위해 이를 자동으로 실행합니다.

맞춤 LifecycleOwner 만들기

rememberLifecycleOwner() API를 사용하면 맞춤 LifecycleOwner를 만들고 기억할 수 있습니다. 이는 특히 HorizontalPager와 같은 구성요소에 유용합니다. 이 경우 표시되고 안정화된 페이지는 RESUMED로 설정하고 인접한 화면 밖 페이지에는 STARTEDmaxState를 설정합니다.

val pagerState = rememberPagerState(pageCount = { 10 })

HorizontalPager(state = pagerState) { pageNum ->
    val pageLifecycleOwner = rememberLifecycleOwner(
        maxState = if (pagerState.settledPage == pageNum) {
            Lifecycle.State.RESUMED
        } else {
            Lifecycle.State.STARTED
        }
    )

    CompositionLocalProvider(LocalLifecycleOwner provides pageLifecycleOwner) {
        // Your pages here. Their lifecycle-aware components respect the
        // custom maxState defined above.
    }
}

CompositionLocal에 관한 자세한 내용은 CompositionLocal을 사용한 로컬 범위 지정 데이터를 참고하세요.

수명 주기 인식 구성요소의 권장사항

  • UI 컨트롤러를 가능한 한 가볍게 유지하세요. 이러한 컨트롤러는 자체 데이터를 확보하려고 해서는 안 됩니다. 대신 ViewModel을 사용하여 데이터를 확보하고 StateFlow 객체를 관찰하여 변경사항을 다시 UI에 반영해야 합니다.
  • 데이터 기반 UI를 작성해 보세요. 여기서 데이터 변경에 따라 UI를 업데이트하거나 사용자 작업을 다시 ViewModel에 알리는 것은 UI 컨트롤러의 책임입니다.
  • ViewModel 클래스에 데이터 로직을 배치하세요. ViewModel은 UI 컨트롤러와 앱 나머지 부분 간의 커넥터 역할을 해야 합니다. 하지만 데이터를 가져오는 것(예: 네트워크에서 데이터 가져오기)은 ViewModel의 책임이 아닙니다. 대신 ViewModel은 적절한 구성요소를 호출하여 데이터를 가져온 후 결과를 다시 UI 컨트롤러에 제공해야 합니다.
  • Kotlin 코루틴을 사용하여 장기 실행 작업 및 비동기적으로 실행될 수 있는 기타 작업을 관리하세요.
  • 실제로 필요한 컴포저블 내에 시작/중지 로직을 유지합니다. 이렇게 하면 특정 UI 요소가 화면에서 삭제되는 경우 (예: 탐색 그래프 내 또는 표시 상태가 조건부인 경우) 로직이 자동으로 삭제됩니다.
  • 데이터에 collectAsStateWithLifecycle 사용 수명 주기 이벤트에 따라 Flow 수집을 수동으로 시작하거나 중지하지 마세요. 대신 collectAsStateWithLifecycle를 사용하여 스트림을 UI 상태로 효율적으로 변환하세요. 앱이 백그라운드에 있을 때 Flow가 일시중지되므로 배터리와 리소스가 절약됩니다.

Flow에 관한 자세한 내용은 기타 지원되는 상태 유형을 참고하세요.

수명 주기 인식 구성요소의 사용 사례

수명 주기 인식 구성요소를 사용하면 다양한 사례의 수명 주기를 훨씬 쉽게 관리할 수 있습니다. 몇 가지 예는 다음과 같습니다.

  • 대략적인 위치와 세분화된 위치 업데이트 간 전환. LifecycleStartEffect를 사용하여 앱이 표시되는 동안 (ON_START) 세분화된 위치 업데이트를 사용 설정하고 앱이 백그라운드에 있을 때(ON_STOP) 리스너를 자동으로 정리하거나 대략적인 위치 업데이트로 전환합니다.
  • 동영상 버퍼링 중지와 시작. LifecycleResumeEffect를 사용하여 앱이 완전히 포그라운드에 있고 대화형 (ON_RESUME)이 될 때까지 실제 동영상 재생을 지연하고 앱이 백그라운드에 있을 때 (ON_PAUSE) 재생이 일시중지되고 리소스가 해제되도록 합니다.
  • 네트워크 스트리밍 시작 및 중지 collectAsStateWithLifecycle를 사용하여 연속 데이터 스트림 (예: 네트워크 소켓의 Kotlin Flow)을 관찰합니다. 이렇게 하면 앱이 포그라운드에 있는 동안 실시간으로 업데이트할 수 있으며 앱이 백그라운드로 전환되면 수집이 자동으로 취소됩니다.
  • 무거운 작업 일시중지 및 재개 LifecycleResumeEffect를 사용하여 앱이 백그라운드에 있을 때 과도한 시각적 업데이트를 일시중지하고 앱이 포그라운드로 전환된 후 다시 시작합니다.

ON_STOP 이벤트를 안전하게 처리

Compose는 ON_STOP 이벤트를 안전하게 처리하도록 설계되었습니다.

  • 상태가 안전함: 앱이 백그라운드에 있는 경우에도 언제든지 MutableState를 업데이트할 수 있습니다 (예: uiState.value = ... 사용). Compose는 앱이 표시될 때까지 기다려 변경사항을 렌더링합니다.
  • 자동 정리: LifecycleStartEffect와 같은 효과를 사용하면 수명 주기가 STOPPED로 이동할 때 정리 블록 (onStopOrDispose)이 정확히 실행됩니다. 이렇게 하면 앱이 백그라운드에 있는 동안 카메라나 위치와 같은 무거운 리소스를 보유하지 않습니다.

MutableState에 관한 자세한 내용은 상태 및 Jetpack Compose를 참고하세요.

추가 리소스

수명 주기 인식 구성요소로 수명 주기 처리에 관해 자세히 알아보려면 다음 추가 리소스를 참고하세요.

콘텐츠 조회