[Android] LiveData...넌 누구냐?

JoJo Develog·2020년 4월 19일
10

Android

목록 보기
15/19
post-thumbnail

안녕하세요.

이번 포스팅의 주제는 LiveData 입니다.

안드로이 아키텍쳐 패턴(MVP, MVM, MVVM 등)에서 빠질 수 없는 것들이 몇가지 존재 하는데요.

그 중에서 저번시간에 소개드린 Databinding에 이어서 이번엔 LiveData입니다.
https://velog.io/@jojo_devstory/Android-Databinding을-알아보자

둘이 같이 쓰면 정말 찰떡궁합인데요.🥳

역시나 이 녀석도 Android JetPack 라이브러리의 하나의 기능 입니다.

한번 이 녀석이 뭐하는 녀석인지 간단하게 개념만 알아보도록 합시다.

1. LiveData란?

LiveData는 Data의 변경을 관찰 할 수 있는 Data Holder 클래스 입니다.
일반적인 Observable과는 다르게 LiveData는 안드로이드 생명주기(LifeCycle)를 알고 있습니다. (Lifecycle-Aware)
즉, 액티비티나, 프레그먼트, 서비스 등과 같은 안드로이드 컴포넌트의 생명주기(Lifecycle)를 인식하며 그에따라 LiveData는 활성상태(active)일때만 데이터를 업데이트(Update) 합니다.
활성상태란 STARTED 또는 RESUMED를 의미합니다.

또한 LiveData 객체는 Observer 객체와 함께 사용됩니다. LiveData가 가지고 있는 데이터에 어떠한 변화가 일어날 경우, LiveData는 등록된 Observer 객체에 변화를 알려주고, Observer의 onChanged() 메소드가 실행되게 됩니다.

2. LiveData가 어떻게 생명주기를 알아요?

바로 LifeCycleOwner이라는 녀석이 안드로이드 생명주기 (Android LifeCycle)를 알고 있는 클래스라 보면 됩니다.
메서드가 오직 getLifeCycle() 밖에 없는 단일 메소드 인터페이스 클래스 이며, Activity나 Fragment에서 이를 상속하고 있습니다.
한 마디로 LiveData의 Observer 메소드의 LifeCycleOwner를 Activity나 Fragment를 변수로써 사용한다면 각 화면 별 생명주기에 따라 LiveData는 자신의 임무를 수행 합니다.

3. 뭔 엄청좋은거 같은데....장점이 뭐죠..?

  • Data와 UI간 동기화
    LiveData는 Observer 패턴을 따릅니다. 그에따라 LiveData는 안드로이드 생명주기에 데이터 변경이 일어날 때마다 Observer 객체에 알려줍니다.
    그리고 이 Observer 객체를 사용하면 데이터의 변화가 일어나는 곳마다 매번 UI를 업데이트하는 코드를 작성할 필요 없이 통합적이고 확실하게 데이터의 상태와 UI를 일치시킬 수 있습니다.
  • 메모리 누수(Memory Leak)가 없습니다.
    Observer 객체는 안드로이드 생명주기 객체와 결합되어 있기 때문에 컴포넌트가 Destroy 될 경우 메모리상에서 스스로 해제합니다.
  • Stop 상태의 액티비티와 Crash가 발생하지 않습니다.
    액티비티가 Back Stack에 있는 것처럼 Observer의 생명주기가 inactive(비활성화) 일 경우, Observer는 LiveData의 어떤 이벤트도 수신하지 않습니다.
  • 생명주기에 대한 추가적인 handling을 하지 않아도 됩니다.
    LiveData가 안드로이드 생명주기에 따른 Observing을 자동으로 관리를 해주기 때문에 UI 컴포넌트는 그저 관련 있는 데이터를 "관찰"하기만 하면 됩니다.
  • 항상 최신 데이터를 유지합니다.
    화면 구성이 변경되어도 데이터를 유지합니다.
    예를 들어, 디바이스를 회전하여 세로에서 가로로 화면이 변경될 경우에도 LiveData는 회전하기 전의 최신 상태를 즉시 받아옵니다.
  • 자원(Resource)를 공유할 수 있습니다.
    LiveData를 상속하여 자신만의 LiveData클래스를 구현할 수 있고 싱글톤 패턴을 이용하여 시스템 서비스를 둘러싸면(Wrap) 앱 어디에서나 자원을 공유 할 수 있습니다.

4. LiveData 사용시 주의 할 점

LiveData 객체를 사용하기 위해서는 다음 내용을 알고 계시면 됩니다.

  • Generic을 사용해 관찰하고자 하는 데이터의 타입(Type)을 갖는 LiveData 인스턴스를 생성합니다.
    (보통 LiveData 객체는 안드로이드 아키텍쳐 패턴의 ViewModel 클래스 내에서 함께 사용됩니다.)

  • LiveData 클래스의 observe() 메소드를 사용해 Observer 객체를 LiveData 객체에 "결합" 합니다. 이때 observe() 메소드는 LifecycleOwner 객체를 필요로 하며 보통은 Activity를 전달합니다.
    LiveData에 저장된 데이터에 어떠한 변화가 일어난 경우 결합된 LifecycleOwner에 의해서 상태가 active(활성)인 한 모든 데이터에 대해 Trigger가 발생합니다.

  • Observer 객체를 생성합니다..
    생성시 LiveData가 들고있는 데이터가 변화가 일어났을 때 수행해야 할 로직이 들어있는 onChanged() 메서드를 정의해야 합니다.
    보통은 액티비티나 프래그먼트 같은 UI Controller 내에서 해당 메서드를 생성합니다.

  • observeForever(Observer)를 통해 LifeCycleOwner 없이 Observer를 생성하여 등록할 순 있지만, 이 경우에는 Observer는 항상 active(활성) 상태이므로 데이터 변화를 항상 전달 받습니다. 단, removeObserver(Observer) 메소드를 통해 Observer를 제거 할 수 있습니다.

5. LiveData의 간단한 사용법 (예제 코드)

앞에서 설명드린 것 처럼 LiveData는 주로 안드로이드 아키텍처 패턴의 ViewModel과 함께 사용되기 때문에, 예제 코드도 ViewModel을 상속받아 클래스 내에서 정의한 LiveData로 작성했습니다.
ViewModel이 무엇인지 알고 싶으시다면 이전 포스팅들을 참조 바랍니다.

예제 코드들은 Kotlin으로 작성했습니다.

  1. ViewModel 클래스 생성
    아래의 코드에서는 MutableLiveData를 사용했지만 불변(Immutable)객체로 LiveData<>를 사용해도 상관없습니다.
class TestLiveDataViewModel : ViewModel() {
    // String 타입의 MutableLiveData 생성, by lazy로 초기화는 뒤에
    val textValue: MutableLiveData<String> by lazy {
        MutableLiveData<String>()
    }
}

위에서 만든 ViewModel 클래스 내의 LiveData 객체를 Activity에서 사용을 할텐데 대부분의 경우 LiveData에 Observer를 결합하는 코드는 컴포넌트의 onCreate() 메소드 내에 위치하는 것이 바람직합니다.
그 이유는 2가지가 있습니다.

  • 안드로이드 생명주기인 onResume()에 하게될 경우 pause()stop() 에 의해서 잠시 백그라운드 상에서 inactive(비활성화)된 앱이 다시 active(활성화)가 되면서 LiveData에 대한 코드가 중복호출이 될 수 있기 때문입니다.
    이는 앞에서 설명드렸던 내용들 중에 LiveData의 장점 중 {생명주기에 대한 추가적인 handling을 하지 않아도 됨}에 대해 반대되는 잘못된 방식입니다.
  • 액티비티나 프래그먼트가 active(활성화) 되자마자 UI에 표시 할 수 있는 데이터를 가질 수 있기 때문에 해당 컴포넌트는 STARTED 상태가 되자마자 LiveData 객체로부터 가장 최신의 값을 수신해야 합니다.
  1. 메인 액티비에의 onCreate에 Observer를 세팅합니다.
class MainActivity : AppCompatActivity() {
    // 전역 변수로 ViewModel lateinit 세팅
    private lateinit var model: TestLiveDataViewModel
 
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
 
        // ViewModel을 가져옵니다.
        model = ViewModelProvider(this).get(TestLiveDataViewModel::class.java)
 
        // Observer를 생성한 뒤 UI에 업데이트 시켜 줍니다.
        val testObserver = Observer<String> { textValue ->
            // 현재 MainActivity에는 TextView가 하나만 존재합니다.
            // 다른 데이터를 받는 UI 컴포넌트가 있다면 같이 세팅 해줍니다.
            tv_livedata_test.text = textValue
        }
 
        // LiveData를 Observer를 이용해 관찰하고
        // 현재 Activity 및 Observer를 LifecycleOwner로 전달합니다.
        model.textValue.observe(this, testObserver)
    }
}

6. 결론

LiveData를 통해서 UI를 업데이트하는 경우 일반적으로 Activity나 Fragment 내에서 직접 선언하는 것보다 위의 예제처럼 ViewModel 내에서 정의하고 호출하여 사용하는 것이 더 좋습니다.
이유는 다들 ViewModel이 뭔지 알고 계시듯이 액티비티와 데이터 간의 결합도를 낮추고(의존성), UI Controller는 오직 data를 display만 하는 것을 수행하게 하는 안드로이드 아키텍처 패턴(디자인)을 유지하기 위해서입니다.

까놓고 말해서 LiveData는 그냥 LiveData만 쓰면 좋은점을 크게 느끼기 힘듭니다.
하지만 Databinding, ViewModel, RoomDatabase, Reactive Programing등과 함께 쓸 경우 그 진가가 발휘되며 개발자는 아주 편하게 코딩이 가능하기 때문에 UI 출력 데이터에 관한 실수 또한 줄여줍니다.

참고내용
https://developer.android.com/topic/libraries/architecture/livedata?hl=ko
https://www.charlezz.com/?p=363
https://aonee.tistory.com/entry/Android-ACC-MVVM패턴-Repository-LiveData-DataBinding-공부-후-프로젝트에-적용해보기
https://readystory.tistory.com/101

profile
12년도부터 대학에서 안드로이드 모바일을 전공으로 시작하여 "진짜 개발자"를 꿈꾸며 개발공부를 시작했습니다. SW 개발이 재밌어서 여러 방면으로 스터디하며 현재는 새로운 환경 및 새로운 트렌드에도 유연하게 적응을 잘하는 개발자로 성장해 나가는 중입니다. 글 내용에 대한 피드백은 언제나 환영입니다!

0개의 댓글