[Android Jetpack] LiveData 사용방법

2021. 1. 24. 16:00바삭바삭 IT/안드로이드

observable을 모르신다면 이 글을 먼저 추천드려요!

2021/01/31 - [바삭바삭 IT/디자인패턴] - [디자인패턴] Observer? Observable?

 

[디자인패턴] Observer? Observable?

안드로이드의 라이브데이터가 구현한 패턴, Observer에 대해 알아봅시다. 우선, 디자인패턴이란 소프트웨어에서 반복되는 문제상황에 대한 해결책입니다. 개발자가 앱이나 시스템을 디자인할때

kimdabang.tistory.com

LiveData는 observable data holder class, 관찰가능한 데이터들을 담는 클래스라는 뜻 입니다. LiveData는 일반적인 observable과는 달리 생명주기를 인식합니다. 즉 앱의 컴포넌트들(액티비티, 프래그먼트, 서비스 등)의 생명주기를 인식하고 있습니다. LiveData가 활동중인 lifecycle상태에 있는 observer들만을 업데이트한다는 것이죠.

 

LiveData는 observer의 생명주기가 STARTED 또는 RESUMED 상태일 경우 활성상태로 파악합니다. LiveData는 활성된 observer에게만  업데이트를 알려줍니다. 비활성화 observe들은 변경사항에 대해 알림을 받지 않습니다.

 

observer를 LifecycleOwner인터페이스를 구현한 객체(액티비티나 프래그먼트 등)과 함께 등록할 수 있습니다. Fragment나 AppcompatActivity는 이미 LifeCycleOwner 인터페이스를 구현하고 있습니다. 하지만 Activity는 구현하고 있지 않아서 Activity를 사용할 경우엔 따로 LifeCycleOwner를 구현해야 합니다.

※참고로 LifeCycleOwner는 LifeCycle객체를 반환하는 getLifeCycle() 함수 하나만 선언된 단순한 인터페이스입니다.

model.getUser().observe(this@MainActivity, user -> {
	//do something..
})

이렇게 쌍으로 넘긴 코드는 lifecycle 객체(코드 상 this@MainActivity)의 상태가 DESTROYED로 바뀔때 observer를 제거 합니다. 이런 방식은 액티비티나 프래그먼트가 LiveData를 안전하게 관찰할 수 있기 때문에 유용하죠. 액티비티와 프래그먼트가 생명주기에서 사라지면 즉시 구독이 취소되어 누수에 걱정할 필요도 없게됩니다. 

 

LiveData를 이럴때 사용한다.

  • ui와 데이터 상태의 일치를 보장
  • 메모리누수가 없음
  • 중지된 활동으로 인한 비정상 종료 없음
  • 생명주기를 수동으로 처리할 필요 없음
  • 최신 데이터 유지
  • 화면 회전, 구성 변경에도 최신 데이터로 즉시 변경
  • 리소스 공유

LiveData객체를 이용하기

1. 특정 데이터 타입을 갖는 LiveData인스턴스를 생성합니다. 보통 ViewModel클래스에서 작업해 줍니다.

class NameViewModel : ViewModel() {

    // Create a LiveData with a String
    val currentName: MutableLiveData<String> by lazy {
        MutableLiveData<String>()
    }

    // Rest of the ViewModel...
}

 

2. onChanged()를 정의하는 Observer객체를 만듭니다. onChanged()는 LiveData객체가 갖는 데이터가 바뀔 때의 작업을 제어합니다.

 

3.observe()를 이용해 LiveData객체에 Observer객체를 연결합니다. observe()는 LivecycleOwner객체와 Observer객체를 받습니다. 이렇게 하면 Observer객체가 LiveData객체에 등록되어 변경사항을 알 수 있습니다. 

일반적으로 LiveData는 데이터가 변경 될 때만 업데이트를 제공하고 활동중인 observer에게만 제공합니다. 근데 예외로 observer가 비활성상태에서 활성상태로 변경 될 때도 업데이트 알림을 받습니다. 또 observer가 두번째로 비활성상태에서 활성상태로 변경되면 활성으로 바뀐 마지막 시간후로 변경된 경우에만 업데이트를 받습니다.

class NameActivity : AppCompatActivity() {

    private val model: NameViewModel by viewModels()

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

        val nameObserver = Observer<String> { newName ->
            // Update the UI, in this case, a TextView.
            nameTextView.text = newName
        }
        model.currentName.observe(this, nameObserver)
    }
}


※ observeForever(Observer)을 이용하면 LifecyleOwner객체와 상관없이 observer를 등록할 수 있습니다. 이 경우 observer는 항상 살아있고 그러므로 항상 변경에 알림을 받습니다. 그리고 removeObserver(Observer)로 observer들을 지울 수 있습니다. 하지만 관리가 어려워 위험할 수 있기 때문에 권장사항은 아니라고 합니다.

 

위 코드 observe()가 호출되면 mCurrentName에 저장된 가장 최근 값을 제공하는 onChanged()가 즉시 호출됩니다. LiveData가 mCurrentName에 값을 설정하지 않는 경우 onChanged()가 호출되지 않습니다.


LiveData객체 업데이트하기

LiveData는 public으로 접근 가능한 데이터를 수정,저장하는 메소드가 없습니다. MutableLiveData클래스는 LiveData를 상속받아 mutable과 thread-safe를 구현한 클래스입니다. MutableLiveData는 setValue(T)와 postValue(T)이 public으로 되어있습니다. LiveData객체에서 값을 수정해야 한다면 MutableLiveData를 사용해야 합니다. 보통 MutableLiveData는 ViewModel에서 사용되고 ViewModel은 수정할 수 없는 LiveData객체만 노출시킵니다.

아래 코드처럼 사용해서 LiveData의 값을 수정합니다.

button.setOnClickListener {
    val anotherName = "John Doe"
    model.currentName.setValue(anotherName)
}

위에서 setValue(T)를 호출하면 observer가 onChanged()를 호출하게 됩니다.

 

※ setValue(T)는 main thread에서만 LiveData를 업데이트 하는 함수입니다. 이 코드를 worker thread에서 실행하면 에러가 납니다. 그럴땐 postValue(T)를 사용하면 됩니다.

 

참고

developer.android.com/topic/libraries/architecture/livedata

반응형