hong's android

[안드로이드] LiveData - AAC (Android Architecture Components) 본문

Android/Jetpack

[안드로이드] LiveData - AAC (Android Architecture Components)

_hong 2023. 2. 28. 11:20

AAC(Android Architecture Components)란?

 

AAC 는 테스트와 유지관리가 쉬운 앱을 디자인하도록 돕는 라이브러리 모음

 

LiveData

관찰 가능한 데이터 홀더 클래스이다. 관찰 가능한 일반 클래스와 달리 LiveData는 수명 주기를 인식한다.

//LiveData.java
private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
           new SafeIterableMap<>();

public void removeObserver(@NonNull final Observer<? super T> observer) {
…
}

public void removeObservers(@NonNull final LifecycleOwner owner) {
…
}

LiveData 옵저버들을 소유하고 있고 LifecycleOwner 통해 옵저버의 상태를 확인한다.

 

Observer 클래스 

Observer 클래스는 LiveData에 LifecycleOwner 인터페이스를 구현한 객체를 넘겨주면서

public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer)

또한 생명주기가 활성화(STARTED, RESUMED) 된 Observer에게만 LiveData는 알림을 준다. 만약 Observer의 생명주기가

일시 중지된다면 LiveData는 알림을 주지 않는다. 만약 액태비티가 다시 실행되어 활성화 상태이면 최신의 데이터를 전송한다.

 

관찰자에 대응하는 Observer의 생명주기가 DESTROYED로 변경될 때  관찰자를 삭제할  있는데 이것은 메모리 누수를방지해 준다.

 

생명주기를 확인하지 못한다면 뷰가 Destroy 되어도 레퍼런스를 가지고 있는 

Observer 살아있는 경우 메모리 누수가 일어난다. LiveData Destroy 된 목록에서 삭제한다.

 

    @Override
        public void onStateChanged(@NonNull LifecycleOwner source,
                @NonNull Lifecycle.Event event) {
            Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
            if (currentState == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            Lifecycle.State prevState = null;
            while (prevState != currentState) {
                prevState = currentState;
                activeStateChanged(shouldBeActive());
                currentState = mOwner.getLifecycle().getCurrentState();
            }
        }

 

LiveData 사용 이점

 

1.UI와 데이터 상태의 일치 보장

LiveData는 관찰자 패턴을 따릅니다. LiveData는 기본 데이터가 변경될 때 Observer 객체에 알립니다. 코드를 통합하여 이러한 Observer 객체에 UI를 업데이트할 수 있습니다. 이렇게 하면 앱 데이터가 변경될 때마다 관찰자가 대신 UI를 업데이트하므로 개발자가 업데이트할 필요가 없습니다.

 

2. 메모리 누수 없음

관찰자는 Lifecycle 객체에 결합되어 있으며 연결된 수명 주기가 끝나면 자동으로 삭제됩니다.

 

3. 생명주기가 중지되어도 비정상 종료 오류 없음

활동이 백 스택에 있을 때를 비롯하여 관찰자의 수명 주기가 비활성 상태에 있으면 관찰자는 어떤 LiveData 이벤트도 받지 않습니다.

 

4. 수명 주기를 더 이상 수동으로 처리하지 않음

UI 구성요소는 관련 데이터를 관찰하기만 할 뿐 관찰을 중지하거나 다시 시작하지 않습니다. LiveData는 관찰하는 동안 관련 수명 주기 상태의 변경을 인식하므로 이 모든 것을 자동으로 관리합니다.

 

5. 최신 데이터 유지

수명 주기가 비활성화되면 다시 활성화될 때 최신 데이터를 수신합니다. 예를 들어 백그라운드에 있었던 활동은 포그라운드로 돌아온 직후 최신 데이터를 받습니다.

 

6. 적절한 구성 변경 (기기 상태 변경으로 인한 예외 처리 )

기기 회전과 같은 구성 변경으로 인해 활동 또는 프래그먼트가 다시 생성되면 사용 가능한 최신 데이터를 즉시 받게 됩니다. 

 

7. 리소스 공유

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

 

public class MutableLiveData<T> extends LiveData<T> {

    /**
     * Creates a MutableLiveData initialized with the given {@code value}.
     *
     * @param value initial value
     */
    public MutableLiveData(T value) {
        super(value);
    }

    /**
     * Creates a MutableLiveData with no value assigned to it.
     */
    public MutableLiveData() {
        super();
    }

    @Override
    public void postValue(T value) {
        super.postValue(value);
    }

    @Override
    public void setValue(T value) {
        super.setValue(value);
    }
}

 

위와 같이 LiveData 확장해서 사용할 있다.

 

LiveData는 항상 Main Thread를 이용한다.

 

아래 메서드는 LiveData 값을 전달하기 위해 사용한다.

 

  • set : MainThread(UI)가 보장될 경우에는 set을 활용한다.
  • postValue : MainThread가 아닌 IO 스케쥴러를 활용하는 경우 postValue를 활용한다.

 

postValue() 또한 아래와 같이 메인스레드에서 결국 실행한다.

 

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

 

결국 메인스레드를 사용하기 때문에 ui 스레드를 사용하지 않는데 LiveData를 사용하는 것은 비효율적이다.

아래와 같은 상황에 선 좋은 방법이 아니다.

 

  • ViewModel보다 더 안쪽인 Repository(UseCase)와 같이 내부에서 LiveData로 값을 가져오는 경우
  • View 업데이트가 없는 코드에서 LiveData 활용하는 경우

 

Reference.

https://thdev.tech/android/2021/02/01/LiveData-Intro/

https://developer.android.com/topic/libraries/architecture/livedata?hl=ko