본문 바로가기
ANDROID/Android Jetpack

[Android/Jetpack] AAC - LiveData

by 주 녕 2021. 7. 21.
728x90

https://developer.android.com/

LiveData

식별 가능한(Observable) 데이터 홀더 클래스

LiveData는 Activity, Fragment, Service 등 다른 앱 구성요소의 수명 주기를 고려(Lifecycle-aware)한다.

수명 주기 인식을 통해 LiveData는 활성(active) 수명 주기 상태에 있는 앱 구성요소 Observer만 업데이트한다. 

→ Observer 객체가 STARTED나 RESUMED 상태이면 LiveData는 Observer를 활성 상태로 간주함

 

LifecycleOwner 인터페이스를 구성하는 객체와 페어링된 Observer를 등록할 수 있다.

→ Observer에 상응하는 Lifecycle 객체가 DESTROYED 상태로 변하면 Observer를 삭제할 수 있음

→ Activity와 Fragment가 LiveData 객체를 안전하게 관찰하고 수명주기가 끝나는 즉시 수신 거부되어 누수 걱정X

 

위의 내용이 이해가 잘 되지 않는다면 이전 포스팅의 AAC-Lifecycle에서 확인하자!

 

[Android/Jetpack] AAC - Lifecycles

이 포스팅에 앞서 MVVM 아키텍처와 AAC에 대해 알아보았다. 이제는 AAC의 5가지 라이브러리를 Android developer 문서를 통해 알아볼 예정이다. Lifecycles에 대한 내용이 잘 이해가 되지 않는다면 MVVM이 어

junyoung-developer.tistory.com

 

LiveData 사용의 장점

  • UI와 데이터 상태의 일치 보장
    • LiveData는 observer 패턴을 따름 → LiveData는 기본 데이터가 변경될 때 Observer 객체에 알림.
      코드를 통합하여 이러한 Observer 객체가 UI를 업데이트할 수 있음. 
    • 앱 데이터가 변경될 때마다 Observer 객체가 대신 UI를 업데이트 하므로 개발자가 업데이트를 할 필요 없음
  • 메모리 누수(Memory leak) 없음
    • Observer는 Lifecycle 객체에 결합되어 있으며 연결된 수명 주기가 끝나면 자동으로 삭제됨
  • Stop 상태의 Activity와 crash가 발생하지 않음
    • Activity가 백스택에 있을 때를 비롯하여 수명 주기가 비활성 상태에 있으면 관찰자는 어떤 LiveData 이벤트도 받지 않음
  • 수명 주기를 더 이상 수동으로 처리하지 않음
    • UI 구성요소는 관련 데이터를 관찰하기만 할 뿐 관찰을 중지하거나 다시 시작하지 않음
    • LiveData는 관찰하는 동안 관련 수명 주기 상태의 변경을 인식하기 때문에 이 모든 것을 자동으로 관리함
  • 최신 데이터 유지
    • 수명 주기가 비활성화되면 다시 활성화될 때 최신 데이터를 수신함
    • 기기 회전과 같은 구성 변경으로 인해 Activity 또는 Fragment가 다시 생성되면 사용 가능한 최신 데이터를 즉시 받음
  • 리소스 공유
    • 앱에서 시스템 서비스를 공유하도록 싱글톤 패턴을 사용하는 LiveData 객체를 확장하여 시스템 서비스를 랩핑할 수 있음
    • LiveData 객체가 시스템 서비스에 한 번 연결되면 리소스가 필요한 모든 관찰자가 LiveData 객체를 볼 수 있음

 

LiveData 사용 방법

  1. 특정 유형의 데이터를 보유할 LiveData의 인스턴스 생성 (일반적으로 ViewModel 클래스에서)
  2. onChanged() 메서드를 정의하는 Observer 객체 생성
    • onChanged() : LiveData 객체가 보유한 데이터 변경 시 발생하는 작업 제어
    • Activity나 Fragment 같은 UI 컨트롤러에 Observer 객체 생성
  3. observe() 메서드를 사용하여 LiveData 객체에 Observer 객체를 연결
    • observe()는 LifecycleOwner 객체 사용 → Observer 객체가 LiveData 객체를 구독하여 변경사항에 관한 알림을 받음
    • Activity나 Fragment와 같은 UI 컨트롤러에 Observer 객체를 연결

 

LiveData 객체 생성

LiveData는 Collections를 구성하는 List와 같은 객체를 비롯하여 모든 데이터와 함께 사용할 수 있는 Wrapper일반적으로 ViewModel 객체 내에 저장되어 getter 메서드를 통해 접근됨

class TestViewModel : ViewModel() {
    // String 타입의 LiveData 생성
    // by lazy를 통해 초기화는 나중에
    val currentName: MutableLiveData<String> by lazy {
        MutableLiveData<String>()
    }
}

 

*MutableLiveData와 LiveData?

Mutable은 말 그대로 변경이 가능한 것이므로 get/set을 모두 사용할 수 있지만 LiveData는 get만 가

→ ViewModel은 언제나 값의 변경이 일어나고 다시 읽을 수 있는 상태로 사용하는 것이고, View는 값의 읽기만 허용하는 것(MVVM)

하지만 필요에 따라 View에서도 값의 변경이 일어나야 한다면 Mutable을 사용할 수 있다.

 

LiveData 객체 관찰

대부분의 경우 앱 구성요소의 onCreate() 메서드는 LiveData 객체 관찰을 시작하기 적합한 곳임

  • 시스템이 Activity나 Fragment의 onResume() 메서드에서 중복 호출을 하지 않도록 하기 위해서
  • Activity나 Fragment에 STARTED 상태가 되는 즉시 관찰하고 있던 LiveData 객체에서 최신 값을 수신하기 위해서

observer가 업데이트 되는 경우 2가지 : 

'LiveData의 데이터가 변경될 때''observer가 비활성→활성으로 상태 변경될 때'

class MainActivity : AppCompatActivity() {

    // 'by viewModels()'를 사용하여 Kotlin 프로퍼티를 위임
    // activity-ktx artifact
    private val model: TestViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // UI를 업데이트하는 observer 생성
        val testObserver = Observer<String> { newName ->
            // UI 업데이트
            textView.text = newName
        }

        // LiveData를 Observer를 이용하여 관찰하고
        // LifecycleOwner로써 현재 Activity와 obsever를 전달
        model.currentName.observe(this, testObserver)
    }
}
  • testObserver를 매개변수로 전달하여 observe()를 호출하면 onChanged()가 즉시 호출되어 currentName에 저장된 최신 값을 제공함
  • LiveData 객체가 currentName에 값을 설정하지 않았다면 onChanged()는 호출되지 않음

 

LiveData 객체 업데이트

LiveData는 저장된 데이터를 업데이트하기 위해 공개적으로 사용할 수 있는 메서드는 없음

대신, MutableLiveData 클래스는 setValue(T) postValue(T) 메서드를 public으로 하여 저장된 값을 수정할 수 있도록 함

→ 모든 경우에 해당 메서드들을 호출하면 observer가 트리거되고 UI가 업데이트 됨 (== onChanged() 메서드가 호출됨)

  • setValue(T) : MainThread(UI)가 보장될 경우
  • postValue(T) : MainThread가 아닌 IO 스케줄러를 활용하는 경우(worker 스레드)

두 메소드 모두 값을 MainThread에 전달하도록 처리하는 것이기 때문에 항상 MainThread에서 사용할 값을 보증함

→ 데이터의 처리가 IO에서 발생해야 하는 경우라면 LiveData 활용은 맞지 않는 것

 

Room으로 LiveData 사용

  • Room 라이브러리는 Observable 쿼리(DAO의 일부)를 지원하며 이 쿼리는 LiveData 객체를 반환함
  • DB가 업데이트될 때 Room에서는 LiveData 객체를 업데이트하는 데 필요한 모든 코드를 생성
    • 생성된 코드는 필요할 때 백그라운드 스레드에서 비동기적으로 쿼리를 실행
    • 이 패턴은 UI에 표시된 데이터와 DB에 저장된 데이터의 동기화를 유지하는데 유용

*Room에 대한 내용은 계속되는 포스팅에서 다룰 예정임!

 

LiveData 확장

  • onActive() 메서드 : LiveData 객체에 active 상태의 observer가 있을 때 호출됨 (업데이트 관찰을 해야 함)
  • onInactive() 메서드 : LiveData 객체에 active 상태의 observer가 없을 때 호출됨 (연결된 상태를 유지할 필요가 없음)
  • setValue(T) 메서드 : LiveData 인스턴스의 값을 업데이트하고 모든 active 상태의 관찰자에게 변경사항을 알림

 

 

by lazy 등 kotlin의 프로퍼티 초기화에 대한 내용은 아래 포스팅 참고

 

[Kotlin] 프로퍼티와 초기화

모든 내용은 Do it! 코틀린 프로그래밍을 바탕으로 정리한 것입니다. 프로퍼티의 접근 코틀린에서 Getter/Setter가 작동하는 방식 * 자바에서는 각 필드에 접근하기 위해서 접근 메서드 Getter/Setter(접

junyoung-developer.tistory.com


reference >

728x90

댓글