Domain/Android

[Android] LiveData

by Donghwan 2021. 4. 23.

Live Data란?

식별 가능한 데이터 홀더 클래스입니다. 식별 가능한 일반 클래스와 달리 LiveData는 생명 주기를 인식합니다. 즉 Activity, Fragment, Service 같은 다른 앱 구성요소의 생명 주기를 고려합니다. 이러한 생명 주기 인식을 통해 LiveData는 활성 생명 주기 상태에 있는 Observer만 업데이트합니다.

Observer는 생명 주기가 STARTED 또는 RESUMED 상태이면 LiveData는 관찰자를 활성 상태로 간주합니다. LiveData는 활성 상태인 Observer에게만 업데이트 정보를 알립니다. LiveData 객체를 보기 위해 등록된 비활성 관찰자는 변경사항에 관한 알림을 받지 않습니다

생명 주기에 관한 LifeCyclerOwner와 관찰에 대한 객체 Observer를 등록하여 LiveData를 관찰 할 수 있다. LifeCyclerOwner로 활성 상태, 비활성 상태를 관찰하여 관찰자를 관리할 수 있습니다. 특히, Activity, Fragment가 LiveData 객체를 안전하게 관찰할 수 있고 Activity, Fragment의 수명 주기가 끝나는 즉시 수신 거부되어 누출을 걱정하지 않아도 되므로 유용합니다.


Live Data 사용의 이점

LiveData를 사용하면 다음의 이점이 있습니다.

  • UI와 데이터 상태의 일치 보장
    LiveData는 Observer 패턴을 따릅니다. LiveData는 수명 주기 상태가 변경될 때 Observer 객체에 알립니다. 코드를 통합하여 이러한 Observer 객체가 UI를 업데이트할 수 있습니다. 앱 데이터가 변경될 때마다 UI를 업데이트하는 대신, 변경이 발생할 때마다 관찰자가 UI를 업데이트할 수 있습니다.
  • 메모리 누출 없음
    관찰자는 생명 주기에 결합되어 있으며 연결된 수명 주기가 끝나면 자동으로 삭제됩니다.
  • 중지된 활동으로 인한 비정상 종료 없음
    Observer의 수명 주기가 비활성 상태(예: 활동이 백 스택에 있음)이면 Observers어떤 LiveData 이벤트도 수신하지 않습니다.
  • 수명 주기를 더 이상 수동으로 처리하지 않음
    UI 구성요소는 관련 데이터를 관찰하기만 할 뿐 관찰을 중지하거나 다시 시작하지 않습니다. LiveData는 관찰하는 동안 관련 수명 주기 상태의 변경을 인식하므로 이 모든 것을 자동으로 관리합니다.
  • 최신 데이터 유지
    수명 주기가 비활성화되면 다시 활성화될 때 최신 데이터를 수신합니다. 예를 들어 백그라운드에 있었던 활동은 포그라운드로 돌아온 직후 최신 데이터를 받습니다.
  • 적절한 구성 변경
    구성 변경(예: 기기 회전)으로 인해 활동이나 프래그먼트가 다시 생성되면 사용할 수 있는 최신 정보를 즉시 수신합니다.
  • 리소스 공유
    앱에서 시스템 서비스를 공유할 수 있도록 싱글톤 패턴을 사용하는 LiveData 객체를 확장하여 시스템 서비스를 래핑할 수 있습니다. LiveData 객체가 시스템 서비스에 한 번 연결되면 리소스가 필요한 모든 Observer가 LiveData 객체를 볼 수 있습니다.

LiveData 객체로 작업

  • 특정 유형의 데이터를 보유할 LiveData의 인스턴스를 생성합니다. 이 작업은 일반적으로 ViewModel 클래스 내에서 이루어집니다.
  • onChanged() 메서드를 정의하는 Observer 객체를 생성합니다. 이 메서드는 LiveData 객체가 보유한 데이터 변경 시 발생하는 작업을 제어합니다. 일반적으로 활동이나 프래그먼트 같은 UI 컨트롤러에 Observer 객체를 생성합니다.
  • observe() 메서드를 사용하여 LiveData 객체에 Observer 객체를 연결합니다. observe() 메서드는 LifeCycleOwner 객체를 사용합니다. 이렇게 하면 Observer 객체가 LiveData 객체를 구독하여 변경사항에 관한 알림을 받습니다. 일반적으로 활동이나 프래그먼트와 같은 UI 컨트롤러에 Observer 객체를 연결합니다.

LiveData 객체 만들기

LiveData는 List와 같은 Collections를 구현하는 객체를 비롯하여 모든 데이터와 함께 사용할 수 있는 래퍼입니다. LiveData 객체는 일반적으로 ViewModel 객체 내에 저장되며 다음 예에서 보는 것과 같이 getter 메서드를 통해 액세스됩니다.

class NameViewModel : ViewModel() {

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

        // Rest of the ViewModel...
    }

참고 : 액티비티, 프래그먼트 대신 ViewModel의 LiveData 객체에 UI를 업데이트하는 객체를 저장해야 합니다.

그 이유는 다음과 같습니다.

  • 액티비티와 프래그먼트가 지나치게 커지지 않게 하기 위해서입니다. 이제 이러한 UI 컨트롤러가 데이터 표시를 담당하지만 데이터 상태를 보유하지는 않습니다.
  • LiveData 인스턴스를 특정 액티비티나 프래그먼트 인스턴스에서 분리하고 구성 변경에도 LiveData 객체가 유지되도록 하기 위해서입니다.

LiveData 객체 관찰

대부분의 경우 onCreate() 메서드는 LiveData 객체 관찰을 시작하기 적합한 장소이며 그 이유는 다음과 같습니다.

  • 시스템이 액티비티나 프래그먼트의 onResume() 메서드에서 중복 호출을 하지 않도록 하기 위해서입니다.
  • 활동 또는 프래그먼트가 활성 상태가 되는 즉시 표시할 수 있는 데이터를 보유하도록 하기 위해서입니다. 앱 구성요소는 STARTED 상태가 되는 즉시 관찰하고 있던 LiveData 객체에서 가장 최신 값을 수신합니다. 이는 관찰할 LiveData 객체가 설정된 경우에만 발생합니다.

일반적으로 LiveData는 데이터가 변경될 때만, 그리고 활성 관찰자에게만 업데이트를 전달합니다. 이 동작의 예외로, 관찰자가 비활성 상태에서 활성 상태로 변경될 때에도 관찰자는 업데이트를 받습니다. 또한 관찰자가 비활성 상태에서 활성 상태로 다시 변경되면 마지막으로 활성 상태가 된 이후 값이 변경된 경우에만 업데이트를 받습니다.

class NameActivity : AppCompatActivity() {

        // Use the 'by viewModels()' Kotlin property delegate
        // from the activity-ktx artifact
        private val model: NameViewModel by viewModels()

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

            // Other code to setup the activity...

            // Create the observer which updates the UI.
            val nameObserver = Observer<String> { newName ->
                // Update the UI, in this case, a TextView.
                nameTextView.text = newName
            }

            // Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
            model.currentName.observe(this, nameObserver)
        }
    }

nameObserver를 매개변수로 전달하여 observe()를 호출하면 onChanged()가 즉시 호출되어 mCurrentName에 저장된 가장 최신 값을 제공합니다. LiveData 객체가 mCurrentName에 값을 설정하지 않았다면 onChanged()는 호출되지 않습니다.


LiveData 객체 업데이트

LiveData에는 저장된 데이터를 업데이트하는 데 공개적으로 사용할 수 있는 메서드가 없습니다. MutableLiveData 클래스는 setValue(T) 및 postValue(T) 메서드를 공개 메서드로 노출하며 LiveData 객체에 저장된 값을 수정하려면 이러한 메서드를 사용해야 합니다. 일반적으로 MutableLiveData는 ViewModel에서 사용되며 ViewModel은 변경이 불가능한 LiveData 객체만 관찰자에게 노출합니다.

관찰자 관계를 설정한 후에는 아래 예와 같이 사용자가 버튼을 탭할 때 모든 관찰자를 트리거하는 LiveData 객체의 값을 업데이트할 수 있습니다.

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

LiveData 확장

관찰자의 수명 주기가 STARTED 또는 RESUMED 상태이면 LiveData는 관찰자를 활성 상태로 간주합니다. 다음 샘플 코드는 LiveData 클래스의 확장 방법을 보여줍니다.

class StockLiveData(symbol: String) : LiveData<BigDecimal>() {
        private val stockManager = StockManager(symbol)

        private val listener = { price: BigDecimal ->
            value = price
        }

        override fun onActive() {
            stockManager.requestPriceUpdates(listener)
        }

        override fun onInactive() {
            stockManager.removeUpdates(listener)
        }
}

이 예에서 가격 리스너 구현에는 다음과 같은 중요한 메서드가 포함되어 있습니다.

  • onActive() 메서드는 LiveData객체에 활성 상태의 관찰자가 있을 때 호출됩니다. 즉, 이 메서드에서 주가 업데이트 관찰을 시작해야 합니다.
  • onInactive() 메서드는 LiveData객체에 활성 상태의 관찰자가 없을 때 호출됩니다.
  • setValue(T) 메서드는 Livedata 인스턴스의 값을 업데이트하고 모든 활성 상태의 관찰자에게 변경사항을 알립니다.
728x90
반응형

댓글