본문 바로가기

Android

Android LiveData

주의

이 블로그는 개인적인 생각과 이해를 정리한 곳입니다. 실제와 다를 수 있으니 글에서 참고한 글을 꼭 확인해주세요.

요약

LiveData는 Observer 패턴으로 구현되어있으며 Android Lifecycle Safety 하게 onChanged 이벤트를 전달해준다. 기본적으로 observe만 가능하지만 MutableLiveData를 사용하면 setValue로 값을 변경할 수 있다. 메인 스레드에서만 값을 변경할 수 있도록 제한되어있기 때문에 주의해야 하고 postValue로 메인 스레드에서 값을 변경할 수 있는 기능을 제공한다.

LiveData란?

Android Jetpack 중 하나인 Lifecycle에서 제공하는 클래스. Observer 패턴으로 구현되어있으며 Android Lifecycle Safety하게 onChanged 이벤트를 전달해 준다.

일반적인 사용방법

LiveData는 일반적으로 ViewModel과 같이 사용되며 ViewModel 내부에서 값을 관리하고 View Component인 Activity, Fragment, View, Service에서 LiveData를 observe 하는 형태로 많이 개발한다. ViewModel 내부에서는 값을 변경하기 위해서 MutableLiveData로 선언을 하고 외부에 노출하기 위해서 LiveData로 getter를 선언하고 이를 View Componenet에서 참조한다.

Example

class TestActivity: AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        val viewModel = ViewModelProvider(this)[TestViewModel::class]
        viewModel.testValue.observe(this, Observer {
            // setText
        })
    }
}

class TestViewModel: ViewModel() {
    private val _testValue = MutableLiveData<String>() // backing property
    val testValue = _textValue as LiveData<String>

    init {
        _testValue.value = "Private & Public"
    }
}

 

값의 변경

MutableLiveData에서 값을 변경하려고 할 땐 setValue와 postValue 2가지를 제공하는데, 내부 구현을 보면 setValue는 메인 스레드가 아닐 경우에 exception을 발생시키지만,postValue는 메인스레드에서 값을 변경하도록 되어있다. 단순하게 용도의 차이라고 하자면..

 

  - setValue: 메인스레드에서 값을 바로 변경!

  - postValue: 메인스레드로 스레드를 변경하고 값을 변경! 자세히 말하자면 메인스레드에 값을 변경하는 작업을 enqueue!

 

LiveData는 Android Lifecycle을 기반으로 동작하도록 개발되어있기 때문일 것으로 생각된다. 메인 스레드가 아닌 다른 스레드에서 값을 변경할 수 있도록 허용할 경우 상태 값에 대한 동시성 문제가 발생하고 이를 대응하기 위해서는 많은 코드가 추가될 테니.. 올바른 대응이라고 생각한다.

LiveData.java

public abstract class LiveData<T> {

    protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }

    @MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }
}

onChanged가 호출되는 시점

setValue 또는 postValue를 한다고해서 무조건 onChanged가 불리는 것은 아니다. 위에서 이야기했듯이, LiveData는 Android의 Lifecycle을 기반으로 만들어졌기 때문에 onChanged가 불려도 되는 시점에만 호출해준다.

 

onChanged가 호출될 수 있는 상태는 lifecycleOwner가 Start 또는 Resume 상태일 때다. 그 외 상태에서는 onChanged가 절대 호출되지 않으며 추가로 Destory 상태가 되면 observer를 해제시켜주기까지 한다.

 

LiveData의 이러한 성격 때문에 View가 null이거나 Activity가 null인 상태 같이 비정상적인 상황에서 Exception이 발생하지 않는 것이다. 게다가 Destory 상태가 되면 observer도 해제시켜주니 메모리 누수 위험 부담도 많이 줄어든다.

참고

'Android' 카테고리의 다른 글

안드로이드 Compose: 선언적 UI 개발의 미래  (0) 2023.09.16
Android Activity - Lifecycle(생명주기)  (0) 2020.09.25
Android Jetpack ViewModel  (0) 2020.09.22
Android Dagger Hilt  (0) 2020.09.08