[Android] Jetpack 컴포넌트 - LiveData(1)

sw·2022년 1월 13일
0

1. LiveData

관찰 가능한(Observable) 데이터 클래스로 Lifecycle을 통해 생명주기를 인식하고 activity나 fragment, service와 컴포넌트들의 생명 주기를 따른다.

  • LiveData는 데이터 변경을 활성화된 Observer를 통해서 알려주는데 주어진 LifecycleOwner의 생명주기가 STARTED 또는 RESUME인 경우에만 Observer활성(active) 상태로 간주한다.

  • LiveDataobserve 메소드를 통해 Observer를 등록할 수 있고, LifecycleOwner 구현체가 DESTROYED 상태가 되면 자동으로 Observer는 내부에서 제거된다.


  • 장점

  1. UI와 데이터 상태의 동기화
    • LiveData는 변화를 Observer에게 알리고 Observer 객체에서 데이터 변경에 따른 UI를 갱신할 수 있다.

  2. 메모리 누수를 방지한다.
    • ObserverLifecycle에 바인딩되며, 생명 주기 상태가 DESTROYED되면 스스로 제거되므로 별도의 리소스를 해제하는 코드를 작성할 필요가 없다

  3. 액티비티가 갑자기 종료될 때도 안전하다.
    • Activity가 백스택으로 들어가는 경우와 같이 Observer가 비활성화된 상태일 때는 LiveData로 부터 어떠한 이벤트도 받지 않아 안전하다.

  4. 생명 주기에 대한 고민을 안해도 된다.
    • LiveDataLifecycleOwner를 위임한 후로 자동으로 생명 주기 상태에 따라 관리한다.

  5. 최신의 데이터를 유지한다.
    • 생명 주기가 비활성화되면 데이터의 변경을 감지하지 않지만, 다시 활성화 되는 시점에 최신 데이터를 다시 가져온다.

  6. 구성 변경에 대응한다.
    • 화면 회전 등과 같은 구성 변경으로 인해 재생성 되더라도 즉시 최신 데이터를 받을 수 있다.

  7. 자원 공유하기
    • LiveData를 상속하여 싱글턴 패턴으로 사용할 수도 있다. 안드로이드 서비스 같은 곳에 한 번만 연결하고, 애플리케이션 내 어디에서나 다중으로 접근하여 이 서비스를 관찰할 수 있다.

2. LiveData 사용

  1. 특정 유형의 데이터를 보유할 LiveData의 인스턴스를 생성한다. 이 작업은 일반적으로 ViewModel 클래스 내에서 이루어진다.

  2. onChanged 메소드를 정의하는 Observer객체를 만든다. 이 메소드는 LiveData가 보유한 데이터가 변경될 때 발생하는 작업을 제어한다. 일반적으로 activity나 fragment 같은 UI 컨트롤러에 Observer 객체를 만든다.

  3. observe(LifecycleOwner, Observer) 메소드를 이용해 LiveDataObserver를 연결한다. 일반적으로 activity나 fragment 같은 UI 컨트롤러에 Observer 객체를 연결한다.

    observeForever(Observer) 메소드를 사용하면 연결된 LifecycleOwner 객체가 없는 Observer를 등록할 수 있다. 이 경우 Observer는 항상 active로 간주되어 항상 데이터 변경에 관한 알림을 받는다.
    removeObserver(Observer) 메소드를 호출하여 이러한 Observer를 삭제할 수 있다.

-> LiveData 에 저장된 데이터 값이 업데이트되면 연결된 LifecycleOwneractive 상태에 있는 모든 등록된 Observer를 트리거한다. 이로 인해 LiveData 에서 보유한 데이터가 변경되면 UI가 자동으로 업데이트 된다.



3. LiveData 객체 생성

  • LiveData는 일반적으로 ViewModel 객체 내에 저장되며 getter 메소드를 통해 액세스된다. 초깃값은 null이다.
class NameViewModel : ViewModel() {

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

    // Rest of the ViewModel...
}
  • 일반적으로 ViewModelLiveData객체를 저장하는 이유는
    1. Activity나 Fragment가 커지는 걸 방지
      (UI 컨트롤러는 데이터 표시 담당만!! 데이터 상태 보유는 x)
    2. LiveData 인스턴스를 특정 activity나 fragment에 의존하는걸 분리시켜서 구성 변경에도 LiveData객체가 유지되도록 하기 위해서!



4. LiveData 관찰

  • onCreate에서 LiveData를 관찰하기 적합한데 그 이유는
    1. onResume()에서 중복 호출을 하지 않기 위해서
    2. activity나 fragment가 active 상태가 되는 즉시 표시할 수 있는 데이터가 포함되도록 하기 위해서다.
      (앱 컴포넌트는 STARTED 상태가 되는 즉시 관찰하고 있던 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)
    }
}



5. LiveData 업데이트

  • LiveData는 읽기만 가능하므로 데이터를 쓰려면 MutableLiveData를 사용해야 한다. MutableLiveData도 생성한 직후의 초깃값은 null이다.

  • setValue(), postValue()로 데이터를 수정한다.
    단, setValue()는 메인 스레드에서만 호출해야 한다. postValue()는 주로 백그라운드 스레드에서 호출하는 용도로 사용된다.

  • postValue()의 경우 값을 설정하는 task를 내부에서 handler를 통해 메인스레드로 전달하는데, 그래서 메인 스레드가 실행되기 전에 postValue()를 여러 번 호출해도 가장 마지막에 설정된 값만 가져온다.

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

0개의 댓글