참고 자료
Android Developer 도큐먼트 - 수명 주기 인식 구성요소로 수명 주기 처리
Android Developer 도큐먼트 - LifecycleObserver
Android Developer 도큐먼트 - LiveData
Android Developer 도큐먼트 - LifecycleOwner
LiveData와 같이 수명주기를 인식해서 수명주기가 onStart(),onResume()일때 Observe객체를 트리거하는 AAC들은 어떻게 UI Controller(Activity, Fragment)의 LifeCycle을 관찰할 수 있는 것일까요?
이는 수명주기 인식 구성요소를 사용함으로써 가능합니다. 이번 포스팅은 LifeCycle과 수명주기 인식 구성요소를 공부해보겠습니다
수명주기 인식 구성요소란 액티비티와 프래그먼트와 같은 다른 컴포넌트의 생명주기 상태 변화에 대응하여 수행되는 컴포넌트입니다.
수명주기 인식 구성요소는 말그대로 UI Controller의 수명주기를 인식합니다. 여기서 이야기하는 수명주기은 UI Controller의 onCreate~onDestroy를 하나하나 이야기 하는 것이 아니라 지금 수명주기 상태가 onStart()이다, onResume()이 되었다처럼, View의 현재 수명주기 상태(states)와 어떤 이벤트(events)로 인해 해당 수명주기 상태가 되었는지를 알리는 것입니다.
수명주기 인식 구성요소를 사용하면 코드를 더 가볍게 만들 수 있고 유지보수하기가 쉬워집니다. 즉 액티비티나 프래그먼트의 생명주기와 관련된 코드를 이 컴포넌트안에 작성하여 코드를 더 깔끔하게 작성할 수 있습니다.
예를 들어 어떤 액티비티가 생성되면서 위치 추적이 시작되고 소멸되면서 위치 추적이 멈추어야 한다면 이를 액티비티 내에서 작성할 수 있지만, 액티비티에는 위치 추척 이외에도 다른 작업을 하는 코드가 많습니다. 특정업무(위치 추적)가 생명주기와 밀접한 작업이라면 이 업무만을 추상화 하자는 개념입니다.(수명주기 인식 구성요소들을 사용해서)
lifecycle AAC
를 사용해야합니다. androidx.lifecycle 패키지는 수명 주기 인식 구성요소를 빌드할 수 있는 클래스 및 인터페이스를 제공하기 때문입니다lifecycle AAC의 구성요소는 3가지가 있습니다
Owner : 생명주기 처리가 필요한 액티비티 또는 프래그먼트를 의미합니다.
Observer: 액티비티 또는 프래그먼트의 생명주기가 변하면, 변화에 대한 이벤트를 받기 위한 클래스입니다. LifeCycleObserver인터페이스를 구현해서 얻을 수 있습니다. ex) activity 상태가 onStart()가 되면 추적을 시작하라는 이벤트가 등록되어있음
Lifecycle: UI Controller의 수명 주기 상태 관련 정보를 포함하며 다른 객체(앞선 Observe인터페이스 구현체)가 이 상태를 관찰할 수 있게 하는 클래스입니다. ex)activity의 수명주기상태를 담고있음
기본적인 구조는 LifeCycle 객체에 Observer를 등록해 놓으면 액티비티나 프래그먼트 등의 생명주기 변경 시 LifeCycle 객체가 등록된 Observer를 실행하는 구조입니다.
먼저 수명주기 상태가 변경되면 변경에 따라 처리할 이벤트를 정의해놓을 Observer가 필요합니다. 이를 위해선 LifeCycleObserver인터페이스를 구현하면 됩니다.
하지만 LifeCycleObserver
를 직접 구현해서는 안되고, 이를 구현하여 작성된 인터페이스인 DefaultLifeCycleObserver
또는 LifecycleEventObserver
를 사용하라고 되어있습니다.
LifeCycleOwner
상태 변경를 관찰하는 콜백 인터페이스입니다. 만약 LifecycleEventObserver
와 DefaultLifeCycleObserver
를 모두 구현하였다면 DefaultLifecycleObserver
의 메서드들이 먼저 호출되고 난 후, LifecycleEventObserver.onStateChanged(LifecycleOwner, Lifecycle.Event)
의 호출이 따라옵니다. DefaultLifeCycleObserver
의 메서드는 생명주기가 변할 시 각각의 메서드를 사용하여 호출하는 구조입니다.LifecycleEventObserver
의 메서드는 한 개 존재하고 생명주기가 변할 시 Event가 넘어오고 그를 분기하여 필요한 코드를 호출하는 구조입니다.// DefaultLifecycleObserver 인터페이스 구현
class MyLifecycleObserver: DefaultLifecycleObserver {
// 필요한 메서드를 구현
override fun onCreate(owner: LifecycleOwner) {
super.onCreate(owner)
Log.d(owner.toString(), "onCreate")
}
override fun onResume(owner: LifecycleOwner) {
super.onResume(owner)
Log.d(owner.toString(), "onResume")
}
override fun onStart(owner: LifecycleOwner) {
super.onStart(owner)
Log.d(owner.toString(), "onStart")
}
}
DefaultLifecycleObserver
를 구현하고 onCreate, onStart 등과 같은 메서드를 오버라이드하여 컴포넌트의 생명주기 상태를 모니터링할 수 있습니다. 만약 이 Observer
를 액티비티에 연결하면 액티비티의 Lifecycle
객체를 얻어서 MyLifecycleObserver 객체와 연결하여 액티비티의 수명주기 변화에 따른 이벤트를 처리할 수 있는 것입니다.Observer
가 준비되었다면 Observer
에게 UI Controller의 수명주기를 알려줄 Lifecycle
객체가 필요합니다. 이 객체가 액티비티나 프래그먼트의 생명주기 변화를 감지하는 역할을 수행합니다. 그리고 생명주기의 변화가 발생하면 등록된 Observer
를 실행해주는 역할을 합니다.Lifecycle
은 관련된 컴포넌트의 생명주기를 추적하기 위해서 두 개의 주요 Enum을 사용합니다.
Event
Lifecycle event는 프레임워크 및 Lifecycle 클래스에게 보내지는 생명주기 이벤트입니다. 이러한 event는 액티비티나 프래그먼트의 콜백 이벤트로 매핑됩니다.
State
Lifecycle 객체에 의해 추적되어지는 컴포넌트의 현재 상태입니다.
위의 그림에서 States를 그래프의 노드라 생각하고 Event를 그러한 노드를 잇는 간선이라고 생각하면 됩니다. 만약 States가 CREATED에서 STARTED가 된다면 ON_START라는 event가 발생하는 것이고 STARTED에서 RESUMED가 되면 ON_RESUME라는 event가 발생하는 구조입니다.
Lifecycle
을 얻기 위해서는 LifeCycleOwner
인터페이스에 정의되어 있는 getLifeCycle()
메서드를 사용해야 합니다.
LifecycleOwner
는 생명주기를 가지고 있음을 나타내는 단일 메서드 인터페이스입니다. getLifecycle()
라는 메서드는 LifeCycle
객체를 리턴합니다.
LifeCycle
객체를 얻기 위해선 Activity와 Framgment가 LifeCycleOwner
인터페이스를 구현하고 있어야 합니다. 실제로 확인해보면 Activity를 만들기 위해 상속받았던 AppCompatActivity
가 상속하는 ComponentActivity
에서 LifecycleOwner
을 구현하고 있을을 확인할 수 있습니다그런데, getLifecycle()의 리턴 객체가 mLifecycleRegisty 라는 값입니다.
LifecycleRegisty
class는 LifeCycle
class를 상속받아 일부 메서드를 오버라이딩한 클래스입니다. 여기서 오버라이딩한 주요 메서드가 addObserver
, removeObserver
등 옵저버 객체를 관리하기 위한 것들입니다. 또한 LifeCycle
의 state를 지정하거나 변경할 수 있는 메서드들도 오버라이딩합니다. 즉 LifeCycleRegistry
class를 이용하여 LifeCycleOwner
를 커스텀하거나 옵져버들을 관리할 수 있는 기능을 제공하도록 해줍니다.
따라서 Activity에서 구현하고 있는 getLifeCycle()
은 LifeCycleRegistry
를 리턴함으로써 외부의 Observer
객체들을 리스트에 저장하고 LifeCycle
state에 따라 관리 할 수 있는 기능을 사용할 수 있게 됩니다
class ExampeActivity: Activity(), LifecycleOwner {
private lateinit var lifecycleRegistry: LifecycleRegistry
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycleRegistry = LifecycleRegistry(this)
lifecycleRegistry.addObserver(MyLifecycleObserver())
}
override fun getLifecycle(): Lifecycle {
return lifecycleRegistry
}
}
AppCompatActivity
를 구현하지 않고 Activity를 상속받아 작성하고 싶다면 직접 LifecycleOwner
를 구현해주어야 수명주기 인식 구성 요소를 사용할 수 있습니다.이제 LiveData
와 같이 수명주기를 인식해서 수명주기가 onStart(),onResume()일때 Observe객체를 트리거하는 AAC들이 어떻게 UI Controller(Activity, Fragment)의 LifeCycle
을 관찰하고, 이벤트를 전달하는 지 알 수 있게됐습니다!
LiveData
의 observe()
를 보면 observe()
의 첫번째 인자가 바로 LifeCycleOwner 구현체
, 두번째 인자가 Observer 객체
입니다. 수명주기 인식 구성요소의 기본적인 구조는 LifeCycle 객체에 Observer를 등록해 놓으면 액티비티나 프래그먼트 등의 생명주기 변경 시 LifeCycle 객체가 등록된 Observer를 실행하는 구조라고 설명한 바 있습니다. 맨 아래 코드를 보시면, owner.getLifecycle()
를 통해 Lifecycle 객체를 얻고 이 객체에 addObserver()
를 호출해 Observer
를 등록하고 있습니다
여기서 중요한건 owner.getLifecycle().addObserver(wrapper)
입니다. owner의 getLifeCycle()
은 LifeCycleRegistry
class의 인스턴스를 리턴하기 때문에 LifeCycleRegistry
가 정의하고 있는 addObserver()
을 사용할 수 있는 것입니다
그리고 if(ower.getLifecycle().getCurrentState()==DESTROYED)
구문을 통해 Lifecycle의 state가 DESTROYED라면 return 하기 때문에 LiveData는 내부적으로 활성 상태일 때만 이벤트를 전달한다는 것을 알 수 있습니다
LiveData의 observe는 인자로 LifecycleOwner을 구현한 객체와 Observe객체를 전달받습니다. 이때 LifeCycle의 서브 클래스인 LifeCycleRegistry 클래스는 addObserve, removeObserve 등 Lifecycle state에 따라 관리 할 수 있는 기능을 제공하는 메서드를 정의합니다. 개발자는 LifeCycleRegistry 객체를 외부에서 사용할 수 있도록 구현해놓은 LifeCycleOwner 를 통해 LiveData와 Observer를 안전하고 편리하게 동작시킬 수 있습니다