ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [LiveData] LiveData를 Background에서도 동작하게 해야 할때
    개발/Android 2018. 5. 1. 20:20
    반응형

     Android Architecture Components 중에 LiveData 클래스가 있습니다. Activity나 Fragment의 생명주기에 따라 동작하는 Observable한 데이터 클래스로 데이터가 변경되면 observe하고 있는 UI로 이벤트가 전달되는 Observer 패턴 방식입니다.

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


     LiveData는 Activity와 Fragment의 생명주기(LifecycleOwner이기 때문이며 별도의 LifeCycleOwner를 구현도 가능합니다.)에 따라 Active / InActive 상태로 전환되며 Active 상태가 아니면 데이터의 변경사항이 있어도 이벤트를 전달하지 않습니다.


    Active : LifecycleOwner가 RESUMED, STARTED일때

    InActive : LifecycleOwner가 그외의 상태일때 

    ※DESTROYED 상태가 되면 자동으로 observe를 해제 합니다.


     위와 같은 특징으로 인해 메모리릭의 염려도 없이 여러 UI 에서 하나의 데이터를 공유하는것이 가능해집니다. 하지만 LifecycleOwner가 Active 상태가 아닌 상황에서도 Data의 업데이트를 받아야 할 상황은 있습니다. Background 상태로 내려갔을때 동작하는 기능이 있다면 InActive상태가 되었을때 데이터를 받아야 합니다. 이럴때를 대비해서 제공되는 observeForever() 메소드가 있습니다.

    참고 : https://developer.android.com/reference/android/arch/lifecycle/LiveData#observeForever(android.arch.lifecycle.Observer<T>)


     문제는 observeForever()를 이용하게 되면 DESTROYED상태일때 자동으로 observe가 해제되는 유용한 기능을 활용을 하지 못하게 됩니다. InActive상태로 전환은 방지하면서 DESTROYED 상태일때의 동작은 유지하기위한 확장 클래스를 만들어 보겠습니다.


    
    public class MutableLiveDataExt extends MutableLiveData {
    
        public void observeSpecific(LifecycleOwner owner, Observer observer, Lifecycle.Event[] states) {
            observe(new SpecificLifecycleOwner(owner, states), observer);
        }
    
        class SpecificLifecycleOwner implements LifecycleOwner, LifecycleObserver {
            private LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this);
            private int eventFlag = 0;
    
            SpecificLifecycleOwner(LifecycleOwner owner, Lifecycle.Event[] states) {
                owner.getLifecycle().addObserver(this);
                eventFlag = makeEventFlag(states);
            }
    
            @Override
            public Lifecycle getLifecycle() {
                return lifecycleRegistry;
            }
    
            @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
            void onStateEvent(LifecycleOwner owner, Lifecycle.Event event) {
                if (!hasEvent(event)) {
                    return;
                }
                
                lifecycleRegistry.handleLifecycleEvent(event);
            }
    
            ...
        }
    }
    
    

     observeSpecific() 메소드를 추가하여 실제 LifecycleOwner와 Observer 객체 그리고 새로 추가한 처리될 이벤트 배열을 전달 받아 내부적으로 새로 생성한 SpecificLifecycleOwner 클래스를 객체화 하여 observe 처리합니다.


    
    public class LiveDataAdv extends MutableLiveDataExt {
        private final Lifecycle.Event[] OBSERVE_STATE = new Lifecycle.Event[]{
                Lifecycle.Event.ON_CREATE,
                Lifecycle.Event.ON_START,
                Lifecycle.Event.ON_RESUME,
                Lifecycle.Event.ON_DESTROY
        };
    
        public void observeAlways(LifecycleOwner owner, Observer observer) {
            observeSpecific(owner, observer, OBSERVE_STATE);
        }
    }
    
    

     SpecificLifecycleOwner에서는 실제 LifecycleOwner의 객체에 addObserver() 메소드를 이용하여 모든 Lifecycle 이벤트를 감시하여 동작해야 할 이벤트를 확인합니다.


     기본이 되는 클래스를 생성하였습니다. 위의 클래스를 이용하여 간단한 코드를 작성해 봅시다. 사용성을 좀 더 높이기 위해서 MutableLiveDataExt를 상속받은 클래스를 생성합니다.


    
    public class LiveDataAdv extends MutableLiveDataExt {
        private final Lifecycle.Event[] OBSERVE_STATE = new Lifecycle.Event[]{
                Lifecycle.Event.ON_CREATE,
                Lifecycle.Event.ON_START,
                Lifecycle.Event.ON_RESUME,
                Lifecycle.Event.ON_DESTROY
        };
    
        public void observeAlways(LifecycleOwner owner, Observer observer) {
            observeSpecific(owner, observer, OBSERVE_STATE);
        }
    }
    
    

     Lifecycle 이벤트중에서 PAUSE, STOP은 처리하지 않도록 제외한 이벤트 배열을 생성합니다. observeAlways() 메소드를 추가하여 내부적으로 observeSpecific() 메소드를 호출합니다.


    
    public LiveDataAdv stringAdv = new LiveDataAdv<>();
    stringAdv.observeAlways(this, new Observer() {
                @Override
                public void onChanged(@Nullable String string) {
                    Log.d(TAG, "observeAlways "+string);
                }
            });
    
    

     LiveData를 상속받아 구현하였기 때문에 observe(), observeForever() 메소드도 사용이 가능하여 기존의 구현되어있는 LiveData 변수가 있는경우 어렵지 않게 마이그레이션이 가능합니다.

    반응형
Designed by Tistory.