LiveData 구조 및 원리

2021. 11. 9. 11:53android

LiveData란?


LiveDataActivityFragment의 생명주기를 관찰하여 Observe하고 있는 값의 변화를 감지할 수 있는 AAC 중 하나입니다. 그럼 어떻게 View(Activity/Fragment)의 LifeCycle을 관찰할 수가 있는 것일까요? LiveData를 알아보기 전에 그 과정을 먼저 알아보려고 합니다.

 

 

LifeCycle AAC


여기서 이야기하는 라이프싸이클은 Activity나 Fragment의 onCreate~ onDestroy를 하나하나 이야기 하는 것이 아니라,  onCreate~OnDestroy를 관찰할 수 있는 Event 및 States를 제공하는 AAC 중 하나를 의미합니다. 또한 Observer들을 lifeCycle에 맞게 관찰하여 변화를 감지하는 Observer List들을 관리합니다. 

 

 

Events : 프레임워크 및 LifeCycle 클래스에서 전달되는 수명주기 이벤트를 말합니다. 이러한 이벤트는 활동과 프래그먼트 콜백 이벤트에 매핑됩니다.

 

States : LifeCycle 객체가 추적한 구성요소의 현재 상태를 의미합니다.

 

기본적으로 Observer가 관측하고 있는 대상의 상태의 변화를 감지할 수 있는 States는 STARTEDRESUMED 일때 변화를 감지하도록 합니다. 

 

기본적으로 LiveData는 Observe 패턴을 통해 관측하고 있는 데이터의 변경을 감지하도록합니다. 그리고 LifeCycle AAC는 Observer들을 해당 LifeCycle의 상태에 따라서 Observer들이 데이터 변화를 감지할 수 있도록 관리해줍니다.

(벌써부터 이 둘을 함께 엮어서 사용하면 좋을 것 같다는 생각이 듭니다!!!)

 

LifeCycleOwner


LifeCycleOwner는 Actvity나 Fragment의 생명주기를 다른 컴포넌트가 관측할 수 있도록 해주는 클래스를 말합니다. 즉 LifeCycle AAC LifeCylceOwner를 통해 제공받을 수 있습니다

@SuppressWarnings({"WeakerAccess", "unused"})
public interface LifecycleOwner {
    /**
     * Returns the Lifecycle of the provider.
     *
     * @return The lifecycle of the provider.
     */
    @NonNull
    Lifecycle getLifecycle();
}

해당 LifeCycleOwner를 들어가보니 LifeCycle 객체를 리턴하는 LifeCycleOwner 인터페이스를 볼 수 있습니다. 따라서 Activity와 Fragment의 LifeCycle을 관측하기 위해서 LifeCycleOwner 인터페이스는 Activity와 Fragment class에서 구현이 되어져야 할 것입니다. 

 

먼저 액티비티는 아래 캡처에서 보이는 것처럼 ComponentActivity에서 LifeCycleOwner를 구현하도록 하고 있습니다.

public class ComponentActivity extends Activity implements
        LifecycleOwner {
        ...
        
        ...
        
        
    @NonNull
    @Override
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }

 

그런데 getLifecylce()에서 리턴되는 객체가 mLifecycleRegistry란 놈입니다!

 

LifecycleRegistry


lifeCycleRegistry class는 LifeCycle Class를 상속받아 일부 메서드를 override한 클래스입니다. 여기서 override한 주요 method는 addObserver, removeObser 등 옵저버 객체를 관리하기 위한 것들입니다. 뿐만 아니라 LifeCycle의 States를 지정하거나 변경할 수 있는 메서드들도 override합니다. 

 

따라서 lifeCycleRegistry class를 이용하여 LifeCycleOwner를 커스텀이 가능할 뿐만 아니라, 라이프사이클 states 등을 변경하고 이에 따른 옵저버들을 관리할 수 있는 기능들을 제공하도록 해줍니다. 

public class LifecycleRegistry extends Lifecycle {

  private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap =
              new FastSafeIterableMap<>();

  private final WeakReference<LifecycleOwner> mLifecycleOwner;

  ...

  public LifecycleRegistry(@NonNull LifecycleOwner provider) {
        this(provider, true);
    }

  private LifecycleRegistry(@NonNull LifecycleOwner provider, boolean enforceMainThread) {
      mLifecycleOwner = new WeakReference<>(provider);
      mState = INITIALIZED;
      mEnforceMainThread = enforceMainThread;
  }

....

}

 

lifeCycleRegistry class의 일부 변수와 생성자입니다. 일부 변수로는 Observer 객체들을 관리하기 위한 mObserverMap, 그리고 LifeCycleOwner를 갖습니다.

lifeCycleRegistry의 생성자를 보면 외부로부터 View의 LifeCycleOwner를 다시 받습니다. 이러한 이유는 액티비티가 구현하고 있는 LifeCycleOwner의 기능에 추가적으로 Observer list 관리 및 LifeCycle States 확장하기 위해서입니다.

만약 lifeCycleRegistry가 순수 View의 LifeCycleOwner를 사용한다면 옵저버 관리를 위한 기능, States를 확장하지 않았기 때문에 사용할 수 없게 됩니다.

 

따라서 액티비티에서 구현하고 있는 getLifeCycle()은 LifeCycleOwner가 아닌, lifeCycleRegistry를 리턴함으로써 외부의 Observer 객체들을 리스트에 저장하고 LifeCycle States에 따라 관리 할 수 있는 기능을 사용할 수 있게 됩니다.

 

그러면 LiveData에서 관찰하고 있는 대상의 Obsever 객체가 어떻게 넘어오는지 코드로 봐보겠습니다. 

public abstract class LiveData<T> {

...

@MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        assertMainThread("observe");
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        owner.getLifecycle().addObserver(wrapper);
    }

	...
}

LiveData의 observe입니다. observe의 첫번째 인자가 바로 LifeCycleOwner, 두번째가 바로 Observer 객체입니다. 여기서 가장 중요한 것은 코드 마지막 부분에 위치한 addObserver(wrapper) 부분입니다.

이처럼 LiveData는 자신이 구현한 Observer 객체를 LifeCycleOwner를 통해 View(Activity/Fragment)가 관리하 Observer list에 전달하도록 합니다. 이로 인해 LiveData가 메모리릭이 방지되고 생명주기에 따라 데이터를 관측할 지 말지를 결정하기 때문에 여러방면으로 이점을 갖게 됩니다.

 

추가적으로 여기서의 LifeCycleOwner의 getLifeCycle()은 lifeCycleRegistry가 되므로 lifeCycleRegistry에서 구현한 addObserver가 됩니다!! 만약 getLifeCycle()의 리턴이 LifeCycle class라면 addObserver는 구현되어 있지 않기에 사용할 수 없게 됩니다. 

public abstract class Lifecycle {
	...
    
    @MainThread
        public abstract void addObserver(@NonNull LifecycleObserver observer);

	@MainThread
    public abstract void removeObserver(@NonNull LifecycleObserver observer);
    
    ...
}

즉 이처럼  LifeCycle class에서 확장하도록 구현된 메서드는 모두 lifeCycleRegistry가 상속받아 확장하고 있으니 액티비티의 getLifeCycle()가 lifeCycleRegistry을 리턴하게 되는 것입니다!

 

 

정리


LiveData를 사용하여 얻는 최대 이점은 현재 선언된 곳의 생명주기에 따라 적절하게 관측되고 관리 되어진다는 것입니다. 

 

이를 위해 생명주기를 관측할 수 있는 LifeCycle class가 제공되고 이 LifeCycle을 확장하여 구현한 LifeCycleRegistry, LifeCycleRegistry 객체를 외부에서 사용할 수 있도록 도와주는 LifeCycleOwner 등을 통해 LiveData 등으로부터 생성된 Observer가 안전하게 동작하게 됩니다.

'android' 카테고리의 다른 글

[Android] Coroutine을 공부하며..  (0) 2021.10.31
디자인 패턴의 차이점  (0) 2021.10.11
2021 네이버웍스 인턴 후기  (3) 2021.09.13
코루틴이란?  (2) 2021.04.29
Glide란?  (0) 2021.01.18