본문 바로가기
Android/JetPack

Jetpack - LiveData

by 봄석 2019. 8. 13.

Jetpack - LiveData

 

AAC LiveData란 ??  ( Android Architecture Components)

LiveData관찰 가능한 데이터 홀더 클래스입니다. 일반 관찰 가능과 달리 LiveData는 수명주기를 인식하므로 활동, 프래그먼트 또는 서비스와 같은 다른 앱 구성 요소의 수명주기를 존중합니다. 이 인식은 LiveData가 활성 수명주기 상태 인 앱 구성 요소 관찰자 만 업데이트하도록합니다.

즉, LiveCycle을 알고있는 DataType이라고 할 수 있습니다.

 

liveData는 observer pattern입니다.즉 데이터의 변경이 일어났을때 ,그 변경을 받아 처리합니다 .

하지만 liveData는 거기다 수명주기를 알고 있습니다. 

그래서 liveData는 수명주기를 존중하여 onStart ,onResume같이 액티비티가 활성화 되어있을때만 변경을 처리합니다 onStop상태같이 다른액티비티로 넘어가 있는 상태라면?? 데이터 변경을 처리하지 않습니다.

마지막으로 다시 원래의 화면으로 돌아와 onResume이 호출된다면,

liveData 는 가장 마지막에 변경된 데이터를 (가장최신데이터) D를 실행합니다.

 

 

 

LiveData를 쓰면 좋은점 !

LiveData를 사용하면 다음과 같은 이점이 있습니다.

  • UI가 데이터 상태와 일치하는지 확인
    • LiveData는 관찰자 패턴을 따릅니다. Observer수명주기 상태가 변경되면 LiveData가 개체에 알립니다 . 이러한 Observer객체 에서 UI를 업데이트하기 위해 코드를 통합 할 수 있습니다 . 앱 데이터가 변경 될 때마다 UI를 업데이트하는 대신 관찰자가 변경이있을 때마다 UI를 업데이트 할 수 있습니다.
  • 메모리 누수 없음
    • 관찰자는 LifeCycle연관된 라이프 사이클이 파괴 될 때 오브젝트 에 바인드되고 스스로 정리됩니다.
  • 활동 중지로 인한 충돌 없음
    • 백 스택의 활동과 같이 관찰자의 수명주기가 비활성 상태이면 LiveData 이벤트를받지 않습니다.
  • 더 이상 수동 수명주기 처리가 필요하지 않습니다
    • UI 구성 요소는 관련 데이터 만 관찰하며 관찰을 중지하거나 다시 시작하지 않습니다. LiveData는 관찰하는 동안 관련 수명주기 상태 변경을 인식하므로이 모든 것을 자동으로 관리합니다.
  • 항상 최신 데이터
    • 수명주기가 비활성화되면 다시 활성화 될 때 최신 데이터를받습니다. 예를 들어, 백그라운드에 있었던 활동은 포 그라운드로 돌아온 직후 최신 데이터를 수신합니다
  • 적절한 구성 변경
    • 장치 회전과 같은 구성 변경으로 인해 활동 또는 조각이 다시 작성되면 사용 가능한 최신 데이터가 즉시 수신됩니다.
  • 자원 공유 
    • liveData 싱글 톤 패턴을 사용하여 객체를 확장하여 시스템 서비스를 래핑하여 앱에서 공유 할 수 있습니다. LiveData객체는 한 번 시스템 서비스에 연결 한 다음 리소스를 필요가있는 관찰자는 바로 볼 수있는 LiveData 개체를. 

 

LiveData 생성하기

LiveData는 어떠한 데이터도 감쌀수 있습니다. 그리고 리스트 같은 Collection구현체를 포함하고있습니다.

라이브데이터 객체는 대게 ViewModel 에 저장됩니다. 

class NameViewModel : ViewModel() {

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

    // Rest of the ViewModel...
}
  • LiveData : LiveData자체는 immutable(불변) 하기 때문에 갱신할 수 없습니다. 
  • MutableLiveData : MutableLiveData는 LiveData를 상속받아 변경가능합니다.
    • postValue : 백그라운드 스레드에서 MutableLiveData를 갱신하기위해 사용합니다.
    • setValue : 메인스레드에서 MutableLiveData 를 갱신하기위해 사용합니다.

 

LiveData 관찰하기

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    val myPriceListener: LiveData<BigDecimal> = ...
    myPriceListener.observe(this, Observer<BigDecimal> { price: BigDecimal? ->
        // Update the UI.
    })
}

observe()호출 이후에  onChanged() 콜백함수를 통해 liveData를 관찰할 수 있습니다.

LifecyclerOwner를 첫 번째 인자로 전달합니다. 이를 통해 LiveData에 Lifecycle소유자와 바인딩합니다.

 

 

LiveData 확장

LiveData는 관찰자의 수명주기가 STARED 또는 RESUMED상태일경우 활성상태로 간주합니다.

 

  • onActive() : LiveData가 활성 옵저버를 갖는지 관찰할 수 있는 콜백 메소드로 ,LiveData가 Active observer 를 하나라도 가질때 호출됩니다. 0 -> 1 
  • onInactive() : LiveData가 활성옵저버를 안가졌는지 관찰할 수 있는 콜백메소드로 ,LiveData가 active observer를 하나도 가지지 않았을 때 호출됩니다. 1 -> 0
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)
    }
}

위의 예에서는 sotckManager가 활성화되어있을때 price를 업데이트하고, 아닐때는 업데이트리스너를 제거합니다.

 

 

LiveData를 더 잘쓰려면 데이터바인딩!

<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
        <variable name="vm" type="MainViewModel" />
    </data>
.........

</layout>

Databinding에서 LiveData를 쓰면 더 편리합니다. 왜냐면 아까와같은 Observe 패턴을 이용해서 UI를 직접 변경해줄 필요 없이

<TextView
    .....
     android:text="@{viewmodel.post.title}"
     
</TextView>

 

아주 깔끔하게 선언할 수 있습니다. 이제 title이 변경되는대로 TextView UI는 알아서 변경이 됩니다.

그렇다면 LiveData Observer UI(Activity, Fragment)가 사라진다면?

더이상 새로운 데이터를 발행하지 않습니다 rx로 따지면 Dispose가 필요없습니다.

 

LiveData 변형

Map

라이브데이터의 변경을 다른 라이브데이터에게 알려주는 메서드입니다.

val userLiveData: LiveData<User> = UserLiveData()
val userName: LiveData<String> = Transformations.map(userLiveData) {
    user -> "${user.name} ${user.lastName}"
}

UserLiveData의 변경사항을 Observe해서 함수를 통해 원하는값으로 변경한뒤 ‘String’을 리턴합니다.

즉 새로운 LiveData를 리턴하는게 아닌 변경된 데이터를 리턴합니다.

 

SwitchMap

SwitchMap은 LiveData를 변경사항을 받아서 다른 LiveData를 발행합니다. 일반적으로 RoomDatabase를 LiveData로 쓸때 많이 사용합니다.

val userIdLiveData:MutableLiveData = ...
val userLiveData:LiveData = Transformations.switchMap(userIdLiveData, id ->
    repository.getUserById(id)) // LiveData를 리턴합니다.

fun setUserId(userId:String) {
     this.userIdLiveData.setValue(userId)
}

SwitchMap은 데이터의 인자값에 따라 다른 LiveData를 발행합니다.

repository.getUserById(id)는 RoomDatabase에서 ID값에 따라 유저값을 가져오며 return값이 LiveData입니다.

SwitchMap을 잘보면 LiveData값을 리턴하고있습니다. 따라서 인자값에따라 다른 데이터소스를 보낼 수 있습니다.

 

MediatorLiveData

Mediator는 중개자 라는 뜻의 단어입니다.

 LiveData liveData1 = ...;
 LiveData liveData2 = ...;

 MediatorLiveData liveDataMerger = new MediatorLiveData<>();
 liveDataMerger.addSource(liveData1, value -> liveDataMerger.setValue(value));
 liveDataMerger.addSource(liveData2, value -> liveDataMerger.setValue(value));

여러 데이터 소스를 한곳에서 Observe할때 사용을합니다.

예를들어 Fragment별로 LiveData<Error>가 있고 이걸

Activity 한곳에서 Crashlistic에 기록한다거나 Toast메세지를 띄울때 Fragment의 LiveData를

Activity의 MediatorLiveData를 통해 사용할 수 있습니다.

'Android > JetPack' 카테고리의 다른 글

Paging3 알아보기  (6) 2021.09.27
AAC - viewModel  (0) 2019.09.02
Jetpack - Paging Library (1)  (0) 2019.08.13
Jetpack - Workmanager (2)  (0) 2019.05.06
Jetpack - Workmanager (1)  (0) 2019.05.06

댓글