- Today
- Total
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 진짜학습지후기
- pullrequest
- KotlinInAction
- 책추천
- 진짜일본어
- webflux
- rxjava
- Android
- 진짜학습지
- androidstudio
- 코틀린
- blog
- github
- suspend
- posting
- 인공지능
- n3문법
- coroutine
- 일본어기초
- CustomTab
- errorhandling
- 학습지
- 책리뷰
- jlpt
- ai
- Kotlin
- GIT
- 안드로이드
- PR
- 일본어문법
코딩하는 개굴이
[안드로이드] LifecycleObserver ( Lifecycle Aware Component 만들기 ) 본문
시작하기 전에 해당 포스팅을 찾아왔다면 Lifecycle 이 무엇인지 알고는 있겠지만 확실히 하기 위해서 잠시 요약해보도록 하자.
Lifecycle
Lifecycle 이란, activity 와 fragment 와 같은 컴포넌트의 lifecycle state 를 들고 있는 정보로, 다른 object 들이 해당 state 를 추적(observe) 할 수 있도록 허용하는 클래스를 말한다.
Lifecycle 은 Event, State 를 활용해 연결된 component 의 수명 주기 상태를 추적한다.
Event 는 프레임워크 및 Lifecycle 에서 전달되는 수명 주기 이벤트로, activity 와 fragment 의 콜백 이벤트에 맵핑되고,
State 는 Lifecycle 객체가 추적한 컴포넌트의 현재 상태를 말한다.
(하위 그래프에서 state 는 node, event 는 edge 라고 생각할 수 있다.)
Lifecycle Aware Component 구현하기
경우에 따라 특정 컴포넌트에 맞춰 함께 서비스가 실행되거나 관찰되어야하는 케이스가 존재할 수 있다. 이럴때 필요한 것이 lifecycle aware component 인데, lifecycle aware component는 activity와 fragment 같은 다른 컴포넌트들의 lifecycle 변경에 따라 작업을 실행한다.
이를 어떻게 구현할 수 있을까?
컴포넌트의 Lifecycle method 안에서 직접 구현?
일반적으로 의존적인 컴포넌트의 lifecycle method 안에서 액션을 구현하는 방식으로 개발을 하지만, 이러한 패턴은 구조상의 복잡도와 오류 증가를 야기할 수 있다. 따라서, Lifecycle aware component 를 사용하여 component 자체로 액션 코드를 옮길 수 있다.
예시로, 아래와 같이 MyActivity 의 lifecycle에 따라 Location Service 를 조절하려한다고 해보자.
internal class MyLocationListener(
private val context: Context,
private val callback: (Location) -> Unit
) {
fun start() {
// connect to system location service
}
fun stop() {
// disconnect from system location service
}
}
class MyActivity : AppCompatActivity() {
private lateinit var myLocationListener: MyLocationListener
override fun onCreate(...) {
myLocationListener = MyLocationListener(this) { location ->
// update UI
}
}
public override fun onStart() {
super.onStart()
myLocationListener.start()
// manage other components that need to respond
// to the activity lifecycle
}
public override fun onStop() {
super.onStop()
myLocationListener.stop()
// manage other components that need to respond
// to the activity lifecycle
}
}
코드를 위와 같이 구성할 경우 실제 onStart/onStop 메서드 안에 로직이 상당하게 들어가야하므로 유지하기가 어려워질 수 있다. 또한, stop 이 start 보다 먼저 수행되어 의도하지 않은 동작이 나올 수도 있다.
LifecycleObserver 를 사용하자.
클래스는 컴포넌트의 라이프사이클을 DefaultLifecycleObserver 를 implement 하여 모니터하여 onCreate, onStart 등을 대응하는 메서드를 오버라이딩 할 수 있다. 그리고 라이프사이클에 addObserver() 메서드로 observer 를 추가한다.
이렇게 하면 원하는 라이프 사이클에 맞게 override 된 부분에서 원하는 로직을 수행할 수 있고, 실제 컴포넌트에 로직이 들어가지 않기 때문에 복잡도도 줄어드는 장점이 있다.
class MyObserver : DefaultLifecycleObserver {
override fun onResume(owner: LifecycleOwner) {
connect()
}
override fun onPause(owner: LifecycleOwner) {
disconnect()
}
}
myLifecycleOwner.getLifecycle().addObserver(MyObserver())
LifecycleOwner
LifecycleOwner는 클래스에 Lifecycle 이 있음을 나타내는 single method interface 로, 해당 인터페이스에서는 getLifecycle() 메서드가 존재한다. 이 인터페이스는 fragment 및 AppCompatActivity 와 같은 개별 클래스에서 Lifecycle을 추출하고, 함께 작동하는 컴포넌트를 생성할 수 있도록 한다.
라이브러리 26.1.0 이상의 fragment 및 activity 에서는 이미 LifecycleOwner 인터페이스가 구현되어있으나, 구현하고자 한다면, 아래와 같은 방법으로 클래스에 State 에 대한 이벤트를 수동으로 전달할 수 있다.
class MyActivity : Activity(), LifecycleOwner {
private lateinit var lifecycleRegistry: LifecycleRegistry
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycleRegistry = LifecycleRegistry(this)
lifecycleRegistry.markState(Lifecycle.State.CREATED)
}
public override fun onStart() {
super.onStart()
lifecycleRegistry.markState(Lifecycle.State.STARTED)
}
override fun getLifecycle(): Lifecycle {
return lifecycleRegistry
}
}
예제
LifecycleObserver 를 생성하여, 해당 lifecycle 에 맞게 string 을 반환하는 lifecycle aware 한 구성요소에 대한 예시를 하나 만들어보도록 하자.
MyLifecycleObserver
조건에 충족할 경우 enable 시킬 수 있도록 하고 해당 값이 true 일 경우 string 을 반환하도록 하였다.
package com.gaegul2moja.lifecycletest
import android.util.Log
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
class MyLifecycleObserver(
private val lifecycle: Lifecycle,
private val callback: (String) -> Unit,
): DefaultLifecycleObserver {
private var enabled: Boolean = false
fun enable() {
if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
enabled = true
}
}
override fun onStart(owner: LifecycleOwner) {
super.onStart(owner)
if (enabled) {
Log.d("TAG", "onStart")
callback.invoke("onStart")
}
}
override fun onCreate(owner: LifecycleOwner) {
super.onCreate(owner)
if (enabled) {
Log.d("TAG", "onCreate")
callback.invoke("onCreate")
}
}
override fun onDestroy(owner: LifecycleOwner) {
super.onDestroy(owner)
if (enabled) {
Log.d("TAG", "onDestroy")
callback.invoke("onDestroy")
}
}
override fun onResume(owner: LifecycleOwner) {
super.onResume(owner)
if (enabled) {
Log.d("TAG", "onResume")
callback.invoke("onResume")
}
}
override fun onPause(owner: LifecycleOwner) {
super.onPause(owner)
if (enabled) {
Log.d("TAG", "onPause")
callback.invoke("onPause")
}
}
override fun onStop(owner: LifecycleOwner) {
super.onStop(owner)
if (enabled) {
Log.d("TAG", "onStop")
callback.invoke("onStop")
}
}
}
MainActivity
main 의 코드는 간단하다. MyLifecycleObserver 를 생성하고, callback 이 오면 그에 맞게 TextView 를 수정할 수 있도록 하였다. 그리고, MyLifecycleObserver 를 enable 시키고 이를 lifecycle 에 Observer 로 등록해두었다.
package com.gaegul2moja.lifecycletest
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
class MainActivity : AppCompatActivity() {
private lateinit var myLifecycleObserver: MyLifecycleObserver
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
myLifecycleObserver = MyLifecycleObserver(lifecycle) { string ->
val textView = findViewById<TextView>(R.id.main_tv)
textView.text = string
}
myLifecycleObserver.enable()
lifecycle.addObserver(myLifecycleObserver)
}
}
결과
TextView 도 로그도 잘 찍히는 것을 볼 수 있다! 간단한 예시이다.
참고 링크
- https://developer.android.com/topic/libraries/architecture/lifecycle#lc-bp
- https://medium.com/@aritrodam773/lifecycle-observer-in-android-6e9d16ed49bc
'안드로이드' 카테고리의 다른 글
[안드로이드] PreferenceFragmentCompat 를 이용해 설정 화면 간단하게 구현하기 (0) | 2023.01.15 |
---|---|
[RxJava3] subscribeOn과 observeOn (0) | 2023.01.01 |
[안드로이드] LifecycleScope 란? (+ LifecycleObserver) (0) | 2022.12.19 |
Android Studio "This version of the Android Support plugin for IntelliJ IDEA (or Android Studio) cannot open this project ... 에러 해결 (0) | 2022.11.07 |
[안드로이드] Activity의 생명주기 (0) | 2022.10.27 |