[Android] AAC - Livedata

ENAN·2021년 6월 25일
0

Livedata란?

Lifecycle을 알고 있는, Observe 할 수 있는 Data holder class

LiveData가 갖고 있는 데이터에 어떠한 변화가 일어날 경우, 등록된 Observer 객체에 변화를 알려주는 방식으로 사용된다.

라이브데이터를 처음 접해 본다면 무슨 말인지 바로 이해하기 힘들 수 있다. 라이브데이터를 제대로 이해하고 사용하기 위해서는 Observer Pattern, Lifecycle 두 가지에 대해 먼저 이해해야 한다.

옵저버 패턴(Observer Pattern)이란?

어떤 객체의 상태 변화를 관찰하는 Observer들의 목록을 객체에 등록하여, 상태 변화가 있을 때마다 등록된 Observer에게 통지하도록 하는 디자인 패턴

LiveData는 데이터를 갖고 있고, 누군가에게 이 LiveData를 관찰(observe)하도록 할 수 있다. 이 때, livedata는 누가 자신을 관찰하고 있는지 자신의 Observer들의 리스트를 갖고 있다. 그러다 LiveData가 갖고 있는 데이터에 어떤 변화가 일어날 경우, 등록된 Observer들에게 변화를 통지해 줌으로써 Observer들은 변화를 감지하게 된다.

흔히 신문 구독을 예시로 많이 드는데, 트렌드에 맞게 유튜브의 경우도 생각해 보자. 시청자들이 어떤 유튜브 채널을 구독(관찰)하면, 유튜버(livedata)가 영상을 올렸을 때(갖고 있는 데이터의 변화가 있을 때) 구독한 시청자들에게 알림을 보내 준다. observer pattern이 이와 마찬가지라고 생각하면 된다.

보면 구독 서비스와 많이 닮은 것 같다는 생각이 드는데, 이처럼 observer 패턴을 발행/구독 패턴이라고도 한다.

  • 참고 (Observer pattern / Pubsub pattern은 다르다?)
    위키에는 observer 패턴을 발행/구독(Publish/Subscribe, 줄여서 Pub/Sub) 패턴이라고도 한다고 나와있지만, 약간의 차이는 있는 것 같다. 의미는 비슷하지만 observer와 subject(객체) 사이에 message broker의 유무 여부에서 오는 결합도 차이 등이 있는데, 자세한 내용은 아래의 링크에 잘 설명되어 있다.
    Observer 패턴과 Publisher/Subscriber(Pub-Sub) 패턴의 차이점

옵저버의 추가, 제거가 자유롭고 객체와 옵저버를 독립적으로 재사용할 수 있다는 점 등 옵저버-객체 간 상호의존성을 최소화 할 수 있으므로 변경에 유연해진다는 장점을 가진다. 이는 MVVM 디자인 패턴에서 얘기하는 목표, 즉 계층 간 의존성을 최대한 없앰으로써 유지보수에서 이점을 가져간다는 목표와도 맞닿아있다는 생각이 든다.

Lifecycle을 알고 있다

생명 주기(Lifecycle)를 알고 있다는 말은, 활성 상태에 있는 컴포넌트의 Observer들만 갱신하는 것이 보장된다는 소리다. 여기서 오는 장점들이 어떤 것들이 있을까 한번 생각해 보자.

우선 view가 destroy되면 알아서 observe 상태를 해제한다. 그래서 메모리 누수의 위험이 없고, 또 백그라운드에서 뷰에 접근하며 에러를 발생시킬 여지도 없다. 또한 기기 회전 등으로 뷰가 다시 생성되면 알아서 데이터를 한번 더 받아오면서 최신 데이터를 유지할 수 있다.

물론 LiveData가 아니라 Rxjava를 써도 lifecycle을 잘 이해하고 처리해 주면 상관 없지만, 대신 개발자가 항상 신경쓰고 관리해야 할 책임이 생기게 된다. 실수가 생길 수 없는 구조와 실수하지 않아야 하는 구조의 차이는 굉장히 크다.

사용 방법

기본적으로 아래와 같이 lifecycleOwner, Observer객체와 함께 사용한다. lifecycleOwner는 Observer가 따라갈 생명 주기를 말하는데 보통의 경우 observer가 선언된 뷰를 owner로 가진다. MainActivity를 lifecycleowner로 갖고 있는 observer는 MainActivity가 종료될 때 같이 메모리에서 해제된다.

  • viewModel에서 liveData 선언, postValue를 통해 값 변경
val itemLiveData = MutableLiveData<List<Item>>()
// 데이터 변경 시
// ex) val stores = some data (List<Item> 형태)
itemLiveData.postValue(stores)
//observer
viewModel.itemLiveData.observe(this@MainActivity) { it->
    // 데이터의 변경을 감지했을 때 실행될 함수를 람다식으로 옵저버에 전달
    // ex) storeAdapter.updateItems(it) 
})

Activity보다는 viewModel에서 정의하고 호출하여 사용하는 것이 좋다. 그래야 Activity는 data를 display하는 역할, 즉 view의 역할만을 수행하게 강제할 수 있기 때문이다. 또한 LiveData를 단독으로 사용할 수 있지만 Databinding, RoomDB 등 AAC의 다른 라이브러리들과 함께 사용하면 훨씬 유용하게 사용할 수 있다.

ex) Room과 함께, DB내용을 관찰해서 자동으로 갱신하기 위해 사용

  • Dao의 getAll 함수 변경 (반환 type을 List<Todo>LiveData<List<Todo>>)
    @Dao
    interface TodoDao {
        @Query("SELECT * FROM Todo")
    //    fun getAll(): List<Todo>
        fun getAll(): LiveData<List<Todo>>
    		. . .
    }
  • DB에 insert 시 자동으로 UI 갱신
    db.todoDao().getAll().observe(this, Observer {todoList ->
                tvTodoList.text = todoList.toString()
            })

    btnTodo.setOnClickListener {
                db.todoDao().insert(Todo(etTodo.text.toString()))
                // tvTodoList.text = db.todoDao().getAll().toString()
            }

vs RxJava(or RxKotlin, RxAndroid)

LiveData와 RxSomething들은 둘다 reactive한 개발 패러다임을 위해 만들어진 라이브러리로, 어떻게 보면 비슷한 역할을 수행한다고 볼 수 있다. 하지만 분명히 차이점은 존재한다. 예전부터 이 차이가 궁금해서 좀 자세히 알아보고 적고 싶었던 주제이지만, 얘기가 길어질 것 같아 다음 글에 적겠습니다!

참고

https://developer.android.com/topic/libraries/architecture/livedata
https://ko.wikipedia.org/wiki/옵서버_패턴
https://jistol.github.io/software engineering/2018/04/11/observer-pubsub-pattern/
https://terry-some.tistory.com/28
https://kscory.com/dev/design-pattern/observer

profile
여정이 곧 보상

0개의 댓글