androidx.lifecycle
패키지는 액티비티나 프래그먼트의 현재 수명 주기 상태를 기반으로 동작을 자동으로 조절할 수 있는 구성요소를 빌드할 수 있는 클래스 및 인터페이스를 제공한다.
LifeCycle 패키지를 이용하기 위해서는 아래와같이 선언한다
dependencies {
def lifecycle_version = "2.5.1"
def arch_version = "2.1.0"
// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
// ViewModel utilities for Compose
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version"
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
// Lifecycles only (without ViewModel or LiveData)
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
// Saved state module for ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"
// Annotation processor
kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
// alternately - if using Java8, use the following instead of lifecycle-compiler
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
// optional - helpers for implementing LifecycleOwner in a Service
implementation "androidx.lifecycle:lifecycle-service:$lifecycle_version"
// optional - ProcessLifecycleOwner provides a lifecycle for the whole application process
implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version"
// optional - ReactiveStreams support for LiveData
implementation "androidx.lifecycle:lifecycle-reactivestreams-ktx:$lifecycle_version"
// optional - Test helpers for LiveData
testImplementation "androidx.arch.core:core-testing:$arch_version"
// optional - Test helpers for Lifecycle runtime
testImplementation "androidx.lifecycle:lifecycle-runtime-testing:$lifecycle_version"
}
일반적으로 액티비티의 수명주기 메서드(onStart, onResume, onPause, onStop.....)에서 필요한 작업을 정의했었다.
아래 코드는 ExoPlayer를 다루는 액티비티 코드중 일부이다
override fun onStart() {
super.onStart()
player.playWhenReady = !leaveByUser
leaveByUser = false
}
override fun onUserLeaveHint() {
super.onUserLeaveHint()
leaveByUser = true
}
override fun onStop() {
super.onStop()
player.pause()
}
일반적으로는 이래도 문제가 없는데, 다른 구성요소들을 다루는 코드가 많아질수록, onStart
, onStop
과 같은 수명주기 메서드는 점점 방대해지고, 때에 따라서는 수명주기 상태에 맞지 않는 호출이 일어날 수도 있다.
public override fun onStart() {
super.onStart()
Util.checkUserStatus { result ->
// what if this callback is invoked AFTER activity is stopped?
if (result) {
myLocationListener.start()
}
}
}
public override fun onStop() {
super.onStop()
myLocationListener.stop()
}
checkUserStatus 메서드가 onStop
호출 이후에 불리는 경우가 있다면????? 아 물론 조건을 따져서 예외처리를 하면 되긴 한다. 하지만 이런 문제들에 대한 구글의 도움이 바로 androidx.lifecycle
패키지인 것이다.
LifeCycle
은 액티비티 / 프래그먼트에서 수명주기 상태정보 및 다른 객체가 이 상태를 관찰할 수 있게 하는 클래스이다.
LifeCycle
은 두가지 Enumeration을 사용해 연결된 구성요소의 수명 주기 상태를 관리한다.
1. 이벤트 : 프레임워크 및 LifeCycle
클래스에서 전달되는 수명 주기 이벤트. 액티비티와 프래그먼트의 콜백 이벤트에 매핑됨. 즉 onResume, onStop등에 매핑된다는것
2. 상태 : LifeCycle
객체가 추적한 구성요소의 현재 상태를 의미
다음 이미지는 상태와 이벤트간의 관계를 나타내는 이미지이다.
상태와 이벤트를 모니터링하고 싶은 클래스는 DefaultLifecycleObserver
를 구현하고, 각 상태에 대한 메서드를 재정의하여 수명주기 상태를 모니터링 할 수 있다
class MyObserver : DefaultLifecycleObserver {
override fun onResume(owner: LifecycleOwner) {
connect()
}
override fun onPause(owner: LifecycleOwner) {
disconnect()
}
}
myLifecycleOwner.getLifecycle().addObserver(MyObserver())
이거 어디서 많이보지 않았는가??? AutoClearedValue!!!
LifeCycleOwner
는 클래스에 LifeCycle
이 있음을 나타내는 단일 메서드 인터페이스이다.
이 인터페이스에는 클래스에서 구현해야 하는 getLifecycle()
메서드가 있다. 인터페이스를 통해 수명주기가 있는 객체와 함께 동작하는 구성요소들을 만들어 낼 수 있다.
즉 예를 들면 아래와 같다
class MyActivity : AppCompatActivity() {
private lateinit var myLocationListener: MyLocationListener
override fun onCreate(...) {
myLocationListener = MyLocationListener(this, lifecycle) { location ->
// update UI
}
Util.checkUserStatus { result ->
if (result) {
myLocationListener.enable()
}
}
}
}
MyLocationListener는 액티비티의 라이프사이클을 제공받아 DefaultLifecycleObserver
를 구현해 라이프사이클에따른 동작을 캡슐화 해서 구현할 수 있다.
즉 LifeCycleOwner
는 그것이 무엇이든 LifeCycle
을 관찰자에게 제공할 수 있으므로, 관찰자가 LifeCycleOwner
의 형태와는 무관하게 동작할 수 있는 방법을 제공해 준다.
또한 LifeCycle
은 현재 상태를 쿼리할 수 있도록 해준다.
fun enable() {
enabled = true
if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
// connect if not connected
}
}
AutoClearedValue????
아까도 말했지만 구글이 프래그먼트에서 뷰바인딩의 참조 문제를 해결하기 위한 방법중 하나로 제시한게 AutoClearedValue 프로퍼티이다.
AutoClearedValue
구현 내용중 init 부분을 보면 알겠지만, 프래그먼트의 lifecycle에 옵저버를 구현하여, onCreate시 해당 프래그먼트의 viewLifeCycleOwner의 lifecycle이 onDestroy를 받을 때 값을 null로 자동으로 치환해 주는 코드를 가지고 있다.
즉 요놈이 LifeCycle및 LifeCycleOwner의 훌륭한 예제가 된다!!!
https://developer.android.com/topic/libraries/architecture/lifecycle?hl=ko
https://thdev.tech/android/2021/11/04/Android-ViewModel-Lifecycle/