티스토리 뷰

반응형

LiveData를 잘 사용하고 싶어서 영상을 보고 정리해봤다. 영상보고 나름대로 이래하고 정리한 내용이므로... 정확한 내용은 영상 확인 ㄱㄱ !! 

 

# livedata 에 대한 google I/O 컨퍼런스 영상 - Fun with LiveData(Android Dev Summit '18) 

https://www.youtube.com/watch?v=2rO4r-JOQtA


[ LiveData 특징 ]

- Simple 

- Lifecycle-Aware

LiveData is Lifecycle-Aware

LiveData는 각 컴포넌트의 Lifecycle을 알고 있기 때문에 관찰자의 상태에 따라 data의 전달여부를 결정한다. 데이터의 값은 유지하면서 lifecycle의 상태에 따라 데이터 전달여부만 달라지기 때문에, 개발자가 데이터 유지를 관리할 필요가 없다.

아래 영상 캡처 화면을 보면... Activity가 foreground 상태일 때(onStart, onResume <- onStop이 호출되기 전까지)만 ViewModel 내에 있는 LiveData가 값을 전달하고 있음을 알 수 있으며, Background 상태에서도 ViewModel의 데이터 변경사항은 자동적으로 적용되고 있음을 알 수 있다.

- Observable

LiveData is an Observable

ViewModel의 data를 각기 다른 Lifecycle을 가진 컴포넌트(Activity, Fragment)에 반영하다보면, Memory Leak, Conflict 등의 문제가 발생할 수 있어... 

이러한 문제는 LiveData를 이용하면 해결할 수 있는데, 관찰대상 데이터를 LiveData로 지정하고 관찰자(컴포넌트)가 관찰대상을 관찰한다고 등록하는 것임.

- Data Holder

LiveData is Data Holder. Not the Stream.

 

 

[ Transformations - map, switchMap, MediatorLiveData ]

LiveData is greate to communicate View and ViewModel. - jose

LiveData는 Observable을 이용하여 View와 ViewModel을 연결한다. 그렇다면 View와 repository는 어떻게 연결해야 할 까? 이 부분은 ViewModel에서 Transformation을 적용하여 data model을 ui data model로 변환시켜 표출하도록 한다.

 

* Key Point : LiveData를 적용시키는데 있어서, 개발자의 추가적 구현없이 자동적으로 LiveData 형태로 변환시킨다는 것이다. 이는 LiveData의 특징인 Lifecycle에 대한 인지기능이 자동적으로 안전하게 추가되어지고 관리된다는 것이다. (Lifecycle propagation)

 

- Transformations.map : One-to-one static transformation 

 fun < X , Y > map ( source : LiveData < X >, func : ( X ) -> Y ) : LiveData < Y > 

LiveData X 를 function을 적용해 LiveData Y 형태로 변환시킨다.

 

- Transformation.switchMap : One-to-one dynamic transformation

 fun < X , Y > switchMap ( source : LiveData < X >, switchMapFunction : ( X ) -> LiveData < Y > ) : LiveData < Y > 

switchMap이 사용되는 상황을 보자. map과 switchMap의 함수를 보면 변환을 위한 function의 리턴 값이 일반 데이터 형태, LiveData 형태로 구분됨을 알 수 있다. 그럼 이렇게 형태가 다르게 적용되어야 하는 상황은 어느 때일까? 

영상 내용(영상:8분)을 확인해보면 언제 사용하는지 예시를 들어준다. 

Ex ) 당신의 application은 userID를 이용해 로그인되어 유지되고 있는 UserManager 부분과 Server의 Database에 있는 User 정보와 통신하는 repository를 포함한다고 가정하자.

만약 새로운 userId로 로그인 된다면, UserManager 내의 user정보 내용이 repository의 user 정보를 바탕으로 변경되어 표출되야 하는데, 이를 수행하려면, 이 두 부분을 연결해야 한다. ( UserManager의 userId가 LiveData이고, repository의 User 객체가 LiveData ) 이때 필요한 것이 바로 Transformation.switchMap이다. 이를 이용하면 매번 userId가 변경될 때마다 해당 함수가 호출되어 기존의 LiveData의 subscription은 해제되고 새로운 LiveData를 얻어 subscription할 수 있다. 이로써, LiveData의 이점들을 사용할 수 있게 한다.

 

- MediatorLiveData : One-to-many dependency

LiveData subclass witch map observe other LiveData objects and react on OnChanged events from them.

LiveData의 변환은 Transformation.map 과 Transformation.switchMap 만 제공한다. 그렇기 때문에 자신의 맞춤 변환과정이 필요할 경우, MediatorLiveData를 사용하여 커스텀할 수 있다. MediatorLiveData는 source를 하나 이상의 LiveData 로 제공할 수 있다. MediatorLiveData는 다른 LiveData로부터 연결되므로, 다른 LiveData 가 변경되었을 때, 해당 함수가 호출된다.

Ex ) 두 개의 LiveData 문자열의 길이의 합을 리턴하는 함수(영상:11분)

 

 

[ Antipatterns ]

- Strogin big objects across Transformations : Each LiveData holds its value

만약 Web Request를 통해 얻은 방대한 양의 String을 LiveData로 변환시키도록 설정한 경우, LiveData의 특성상 해당 String 객체는 계속해서 memory에 남아 유지되기 때문에 문제가 발생한다. 우리는 해당 요청이 한번만 수행되고 말길 바라기 때문이다.

 

- Sharing instances of LiveData : My repository is Singleton and there's only one observer so I can just share a single LiveData

만약 내가 LiveData를 이용하여 app을 만든다고 가정하자. 그리고 repository는 Singleton으로 되어 있다. 그리고 Activity는 오직 하나의 observer를 가지고 있다. 그리고 item을 load하는 부분에서 MutableLiveData를 이용하도록 구현했다고 하자. 이부분은 잘 동작된다. 그러나 특정 케이스 때문에 antipattern이 되는데, 이 케이스는 Activity transition 이다. 여기서 Activitiy transition이란 Activity1에서 Activity2 로 변경되는 부분이다. Activity가 전환되는 과정에 동일한 시간 대에 두 Activity는 활성화(active) 된다. 

[ Activity transition ]

상상해보자. activity1이 item1을 관찰하고 있다. 그리고 activity2 가 item2를 관찰하고 있다. 이런 상태에서 activity2로 화면을 전환할 때, item2가 load 될 것이다. 그런데 동일한 LiveData를 공유하고 있다면, Activity1도 활상화 되어 있는 과정이므로 item을 계속해서 받고 있을 것이다. 그러면 화면 전환 animation 에서 반짝거림이 발생할 것이고, 이는 UX에 좋지 못하다. 이에 대한 해결방법은 매번 새롭게 LiveData를 생성하는 것이다. 매번 생성하는 과정이 가볍기 때문에 가능하다.

 

 - Transformation setup : Transformations outside initialization

언제, 어디서 Transformation을 생성해야하는지에 대한 부분이다.  

Ex ) 잘못된 Transformation 사용

우선 itemData가 val이 아닌 var 로 정의되어 있으며, MutableLiveData 를 이용했다. ( 대체적으로 이렇게 사용하지 않는다. - 만약 two-way data binding 이면 아마도 이 부분에서 exception이 날 것이다. ) data를 관찰하여 표출하고 싶다면 immutable을 이용해야 변경사항을 관찰할 수 있다.

두번째로, activity로부터 id를 가져와서 data를 load 한다. 우리는 itemData가 새롭게 재할당되길 원한다. 그러나 이미 subscription되어 있는 상태이므로, 관찰자는 새롭게 재할당되었는지 알 수가 없다.

잘못된 Transformation 에 대한 해결방법 => requires a little bit of planning.

2개의 LiveData를 가지며, 하나는 MutableLiveData, 다른 하나는 LiveData로 ViewModel에 존재하도록 한다.

여기서 MutableLiveData는 private으로 LiveData는 View에 표출되어지는 형태로 한다.

아래와 같이 Transformation.switchMap을 이용하여 mutableLiveData인 id에서 itemData를 LiveData로 가져온다.

View에서는 id만 넘겨주면 자동적으로 변경된 id에 따른 itemData가 제공된다.

 

[ LiveData를 사용하면 안되는 상황 ]

- If you need a lot of operators or streams, use Rx.

데이터를 처리하는데 있어 많은 양의 연산이 필요하거나, stream 데이터를 사용해야할 경우, Rx Java를 이용해라.

굳이 LiveData를 이용해서 많은 양의 transformation을 수행할 필요 없다.

- If your operations are not about UI or lifecycle, use callback interfaces.

UI나 Lifecycle이 없는 작업을 수행하는데 있어 liveData를 사용하지 않는다. 

- If you have one-shot operation chaning, use coroutines.

-> 즉, LiveData는 UI를 위한 마지막 layer에서 사용하는 것이 옳은 설계 방식이다.

 

 

[ LiveData 참고 ]

반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함