https://developer.android.com/topic/libraries/architecture/livedata?hl=ko#create_livedata_objects
https://velog.io/@eoqkrskfk94/LiveData%EC%99%80-Flow
https://dev-imaec.tistory.com/39
https://dev-imaec.tistory.com/404


  • LiveData
    • observable data holder = Data의 변경을 관찰 가능한 데이터 홀더 클래스
    • data가 변경될 때마다 알림을 받음
    • 다른 일반 observable class와는 달리 LiveData는 Lifecycle(생명주기)를 인식함.
    • Flow와는 달리 lifecycle을 인식해 Activity, Fragment 등의 다른 components들의 lifecycle도 고려 -> 다른 앱 구성요소인 Activity, Fragment, service 등의 수명주기를 고려한다는 의미.
    • 수명주기를 인식하기 때문에, active lifecycle state에 있는 앱 구성요소의 Observer class로 표현되는 Observer에게만 업데이트 정보를 알림.
    • 즉, LiveData는 UI에서 사용(use)하거나 표시(display)하는 변경 가능한(changeable) data에 적합한 component
    • LiveData는 Observer 객체와 함께 사용해, LiveData가 가지고 있는 data의 변경을 관찰하고 변경이 일어나면 Observer 객체에 이를 알려주어(전달하여) Observer객체의 onChanged()을 수행하게끔 함.
    • 생명주기를 알고 있음. -> LiveData는 생명주기를 인식하여 Activity와 Fragment 등의 생명주기를 따름
    • LiveData는 보통 ViewModel과 함께 사용됨. -> ViewModel 안에 LiveData로 유효한 데이터를 랩핑하고 있게 된다. -> Activity 혹은 Fragment에서 이 LiveData에 변화가 있는지를 파악할 수 있다.
    • Activity가 recreated 되거나 rotated되거나 하여 화면이 재구성하게 될 때 View를 다시 그려야된다.(onCreate를 다시 진행)
      때문에, 기존에 가지고 있던 Activity, Fragment 단의 메모리가 날아가게 되는데 ViewModel Scope은 계속 살아있기 때문에 이 ViewModel에 데이터를 가지고 있게 하면 메모리에서 해당 데이터가 사라지지 않기 때문에 LifeCycle 관리에 효율적이고, View 재구성 시에도 유지된 데이터를 그대로 사용할 수 있다.

  • LiveData의 이점
    • LiveData는 Observer pattern을 따르기에, 기본 데이터가 변경될 때 Observer 객체에 변경되었음을 알림.

      작성한 code를 통합하여 이러한 Observer 객체에서 UI를 업데이트할 수 있음. 이렇게 하면 앱 데이터가 변경될 때마다(viewModel의 LiveData가 변경될 때마다) Observer가 대신 UI를 업데이트하므로 개발자가 따로 UI를 업데이트하는 과정을 거칠 필요가 없음.

    • Observer 객체는 LifeCycle 객체에 결합되어 있으므로 연결된 수명 주기가 끝나면 자동으로 삭제

    • Activity가 back Stack에 있을 경우를 비롯하여 Observer의 수명 주기가 inactive 상태에 있게 된다면, 어떠한 LiveData Event도 받지 않게 할 수 있음.

    • UI 구성요소는 관련된 data를 관찰하기만 할 뿐 observation을 중지하거나 다시 시작시킬 수 없음. -> LiveData는 관찰하는 동안 관련 생명주기 상태의 변경을 인식하기 때문에 이 모든 것을 자동으로 관리함. 즉, 생명주기를 더 이상 수동으로 처리하지 않음

    • 생명주기가 비활성화된 후 다시 활성화될 때 바로 최신 데이터를 받아와 적용함. 즉, 앱 구성요소는 STARTED 상태가 되는 즉시 관찰하고 있던 LiveData 객체에서 최신 값을 수신함

    • 기기 회전과 같은 구성 변경으로 인해 Activity 또는 Fragment가 다시 생성(reCreated)되면 사용 가능한 최신 데이터를 즉시 받아 적용하게 됨.

    • 앱에서 System service를 공유할 수 있도록 싱글톤 패턴을 사용하는 LiveData 객체를 확장하여 시스템 서비스를 래핑할 수 있음. LiveData 객체가 Syetem service에 한 번 연결되면 리소스가 필요한 모든 Observer가 LiveData 객체를 관찰할 수 있음. -> 즉, 리소스 공유가 가능


  • Names for backing properties
    • LiveData를 구성할 때 backing properties 활용
      • 클래스에 개념적으로는 동일하지만 다른 2개의 property를 만든다.
      • 하나는 public한 API의 일부로 쓰이고, 다른 하나는 세부 구현 정보를 나타낸다.
      • private한 mutable val property에 접두사로 밑줄(underscore)를 사용한다.
    • 해당 클래스 안에서 값이 변경되는 mutable 멤버 변수 이기에 private를 붙이며,
    • 값을 변경할 수 있기에 mutable로 선언한 후(_elementList), underscore를 붙여 다른 멤버변수와 구분한다.
    • 같은 값을 나타내지만 underscore이 붙지 않은 다른 멤버변수(elementList)는 다른 클래스나 외부에서 _elementList에 접근할 때 사용하는 용도로 쓰인다.
    • underscore가 없는 멤버변수(elementList)는 외부에서 값을 읽기전용으로 불러올 수 있지만, 값을 변경하지 못하게 해야되므로 mutable이 아닌 그냥 List로 자료형 타입(Element 타입을 가지는 리스트 자료형)을 지정해주는 것이다.
    • getter를 사용해서 외부에서 elementList에 접근하게 되는 경우를 생각한다면,
    • mutable한 멤버변수인 _elementList인 mutableListOf를 get()으로 가져오는 구조인 것이다.
class C {
	private val _elementList = mutableListOf<Element>()
    
    val elementList : List<Element>
    	get() = _elementList
  
  ....
  ....
  
  _elementList.value = ~~~ // 이런 식으로 Mutable의 값을 변경
  
}

  • LiveData Observer Example (Android Developer)
// viewModel class 단에서 특정 타입의 data를 hold하고 있을 LiveData 객체 생성
// 단, MutableLiveData는 ViewModel에서 사용되며 ViewModel은 변경이 불가능한 LiveData 객체만 Observer 객체에게 노출 시킴. -> 이와 관련된건 다음 문단에서 서술
// ViewModel은 기본적으로 UI 관련 데이터를 로드하고 관리하는 역할을 하므로 LiveData 객체를 보유하는 데 적합. LiveData 객체를 ViewModel에 만들고 이를 사용하여 UI 레이어에 상태를 노출.
class NameViewModel : ViewModel() {

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

    // Rest of the ViewModel...
}


// 일반적으로 Activity 혹은 Fragment 단 같은 UI Controller에서 Observer 객체 생성
// Activity와 Fragment같은 UI Controller 단에서는 data 상태(State) 보유가 아닌 data를 표시하는 역할을 하므로 LiveData 인스턴스를 보유해서는 안됨.
class NameActivity : AppCompatActivity() {

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

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

        // Other code to setup the activity...

       
        // 액티비티단에서 Observer 객체 생성
        // Create the observer which updates the UI. 
        val nameObserver = Observer<String> { newName ->
            // LiveData 객체가 보유한 데이터 변경 시 발생하는 작업 제어
            // Update the UI, in this case, a TextView.
            nameTextView.text = newName
        }

		// viewModel의 MutableLiveData에 Observer객체를 연결하여 관찰하기 시작함.
        // observe() 메소드를 이용해 LiveData 객체에 Observer 객체 연결 -> Observer 객체가 해당 LiveData 객체를 관찰 할 수 있게 됨.
        // observe() 메소드는 LifeCycleOwner 객체 사용 -> Observer 객체가 LiveData 객체를 구독하여 변경사항에 관한 알림을 받을 수 있게 됨.
        // Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
        // currentName은 viewModel에서 선언한 MutableLiveData
        viewModel.currentName.observe(this, nameObserver)
    }
}

  • MutableLiveData는 ViewModel에서 사용되며 ViewModel은 변경이 불가능한 LiveData 객체만 Observer 객체에게 노출 시킴.
    ex)
// ViewModel에서 LiveData에 대한 데이터 관리
class NumberViewModel : ViewModel() {

    // MutableLiveData는 ViewModel에서 관리
    // MutableLiveData는 값이 변경되기에 underscore를 붙임
    private val _curNumber = MutableLiveData<Int>()

    // LiveData
    // ViewModel class 외부에서 MutableLiveData에 access하기 위해서는
    // 값 변경이 불가능한 일반 LiveData 변수의 getter를 통해서
    // MutableLiveData 값에 접근해 가져오게 된다.
    // 리턴타입은 Int LiveData
    val curNumber : LiveData<Int>
        get() = _curNumber

    init {
        // 초기값 설정
        _curNumber.value = 0
    }

    fun calculation(option : String, inputValue : Int) {
        when (option) {
            "+" ->
                _curNumber.value = _curNumber.value?.plus(inputValue)
            "-" ->
                _curNumber.value = _curNumber.value?.minus(inputValue)
        }
    }
}  


  • 정리 1)
    • Mutable Live Data => 값을 변경, 수정 할 수 있음
    • 기본 Live Data => 값이 변경, 수정 안됨.

  • 정리 2)
    ViewModel은 Repository의 data를 Flow에서 LiveData로 변환하고 이 data를 LiveData로 UI에 expose시킴. -> 이런 식으로 구조를 구축하면, Database의 data가 변경될 때마다 UI가 자동으로 업데이트됨.


    ex)
profile
https://github.com/nohjunh

0개의 댓글