Android(+ Kotlin)

MVVM 따라하기 Data Binding + LiveData(2)

Charko 2020. 1. 9. 18:43

2019/12/20 - [Android(+ Kotlin)] - MVVM 따라하기 Data Binding, LiveData (1)

 

MVVM 따라하기 Data Binding, LiveData (1)

github 검색 앱을 만들고 관련된 주요내용을 설명한다. https://github.com/CharkoT/CoroutineTester CharkoT/CoroutineTester MVVM + databinding + livedata + coroutine. Contribute to CharkoT/CoroutineTeste..

charko.tistory.com

1편에서는 Data Binding을 위한 작업들을 알아보았다면 2편에서는 LiveData에 대해 알아본다.

 

MVVM 구조를 보면 위와 같은 구조로 설명하는 경우가 많다.

 그래서 ViewModel(이하 vm)에서 LiveData를 사용하는 방법에 대해서 알아본다.

 

https://developer.android.com/topic/libraries/architecture/livedata

 

LiveData 개요  |  Android 개발자  |  Android Developers

LiveData를 사용하여 수명 주기를 인식하는 방식으로 데이터를 처리합니다.

developer.android.com

LiveData의 이점

(위 링크 참조)

  • Ensures your UI matches your data state(UI - data state 일치 보장)

(Mutable) LiveData는 내부 클래스를 보면 observe 메서드를 통해 LifecycleBoundObserver 클래스를 통해 Observer패턴이 동작할 수 있게 구성되어 있다. Lifecycle을 통해 상태가 변경될 때 onStateChanged매서드가 호출되어 Lifecycle 상태에 따라 동작한다.

class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
	@NonNull
	final LifecycleOwner mOwner;
	
	LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
	    super(observer);
	    mOwner = owner;
	}
	
	@Override
	boolean shouldBeActive() {
	    return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
	}
	
	@Override
	public void onStateChanged(@NonNull LifecycleOwner source,
	        @NonNull Lifecycle.Event event) {
	    if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
	        removeObserver(mObserver);
	        return;
	    }
	    activeStateChanged(shouldBeActive());
	}
	
	@Override
	boolean isAttachedTo(LifecycleOwner owner) {
	    return mOwner == owner;
	}
	
	@Override
	void detachObserver() {
	    mOwner.getLifecycle().removeObserver(this);
	}
}
  • No memory leaks

Lifecycle에 결합되어 수명주기가 끝나면 자동 삭제.

위 코드 onStateChanged 매서드내 DESTROYED상태일 때 removeObserver매서드 호출.

 

  • No crashes due to stopped activities (중지된 활동으로 인한 비정상 종료 없음)

상태에 따라 Observer패턴 연결이 끊어지고, 재접속시 다시 연결된다.

  • No more manual lifecycle handling(수명 주기를 더 이상 수동으로 처리할 필요 없음)

수명 주기가 변경될때 자동으로 변경한다.

 

  • Always up to date data(항상 최신 데이터 유지)

수명 주기에 따라 자연스럽게 호출된다. 하지만 별도의 작업이 필요하다.

상태 변경에 따라 onActive() 매서드가 호출되어 해당 클래스를 상속받아 사용한다면 최신 데이터 조회할 수 있게 구성이 가능하다.

 

  • Proper configuration changes(적절한 구성 변경)

 

위 두개의 의미와 유사하지만, 화면이 회전이 일어날 때 해당 데이터가 최신으로 업데이트된다.

 

  • Sharing resources(리소스 공유)

싱글톤 패턴을 사용하는 LiveData 개체를 확장하여 시스템 서비스를 앱에서 공유하도록 래핑할 수 있습니다. LiveData 개체가 시스템 서비스에 한 번 연결되면 리소스가 필요한 모든 관찰자는 LiveData 개체를 바로 관찰할 수 있습니다. 자세한 내용은 LiveData 확장을 참조하세요.

번역된 내용인데 이해가 되지 안된다..;;;

대신 Extend 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)
    }
}

위 코드를 확인해보면 LiveData를 상속받아 onActive(), onInactive()를 오버라이드 한 것을 볼 수 있다

onActive - 상태 변경(destory제외) 호출되는 매서드

onInactive - 상태 변경(destory)될 때 호출되는 매서드

그래서 테스트 코드에는 아래와 같이 적용하였다.

class SearchNickLiveData<T>() : MutableLiveData<T>() {
  override fun onActive() {
    super.onActive()

    getQuery()
  }
}

이 기능을 통해 화면 전환이 이루어질 때 자동으로 최신 데이터를 호출한다.

 

* 그리고 LiveData를 확인하면서 특이한 점을 확인했다.

https://github.com/android/databinding-samples/blob/master/BasicSample/app/src/main/java/com/example/android/databinding/basicsample/data/ProfileObservableViewModel.kt

 

 

 

샘플 코드를 보면 동일한 변수가 동일한 역할을 하는 변수가 2개가(private 있는 것 없는 것) 있는 것을 확인했다.

왜 이렇게 되어있까 추리해보았다.

livedata의 변수는 수정되지 않아 외부에서 공개(Databinding을 위해 공개되어짐)를 한 것이고 Mutablelivedata는 데이터 수정이 가능하여 class내부에서 조작할 수 있게 해 둔 것으로 oop의 3대 요소 중 캡슐화를 지키기 위한 것으로 생각됩니다.