본문 바로가기
android

Android LiveData 알아보기 (feat.ViewModel,Room)

by junmong 2020. 5. 25.

LiveData는 관찰가능한(Observable) 데이터 홀더 클래스이다. 일반적인 관찰가능함과는 다르게, LivaData는 Activity, Fragment, Service 같은 앱 컴포넌트의 생명주기를 인식하고, 그대로 따르도록 구현되어 있다. 이는 LiveData가 현재 활성화된 생명주기에 있는 앱 컴포넌트의 옵저버(Observer)만 업데이트하도록 보장한다.

 

LiveDataLifeCycle을 알고 있는 DataType 이라고 생각하면 될 것 같다.

낄낄빠빠로 필요할때 변경하고 필요하지 않을때 변경하지 않는다.

 

LiveDataObserver 패턴이다 즉 변경이 일어났을때 콜백으로 받아 처리할 수 있다

이렇게 데이터의 변경이 될때마다 콜백을 실행하는데 LifeCycle을 알기때문에 필요하지 않을땐 콜백이 실행되지 않습니다. 예를들어 Activity에 선언되어있는 LiveData의 경우 ActivityStart, Resume 상태일때는 콜백을 실행하지만 다른 액티비티로 넘어가있는 OnStop 등의 상태일때는 실행되지 않는다.

이렇듯 onStart, onResume의 상태일때 AB를 받는 옵저버 콜백을 실행되지만 CD일때는 실행되지 않다고 다시 실행됬을때 가장 최신의 데이터인 D를 실행합니다. 이렇듯 LiveData를 사용하면 RxInterface Callback을 사용할때보다 더 깔끔하게 처리를 할 수 있습니다.

또한 ACC ViewModel에서 사용할경우 ViewModel을 만든 AcitivtyFragmentLifeCycle과 동일하게 작동함

 

LiveData 사용시 장점

LiveData는 다음과 같은 장점이 있다.

  • UI를 데이터 상태와 일치시킬 수 있다.

    • LiveData는 옵저버패턴을 따르고 있다. 생명주기 상태에 변화가 생기면 LiveData는 Observer 인스턴스에 알림을 보낸다. 그러므로, 개발자는 Observer 객체 안에서 UI가 갱신되도록 코드를 통합할 수 있다. 앱의 데이터가 변할때마다 매번 UI를 갱신하는 대신, 옵저버에 변화가 감지될 때마다 UI를 갱신하도록 바꿀 수 있다.

  • 메모리 릭의 요소를 없앨 수 있다.

    • 옵저버들은 Lifecycle 객체와 바인드되고, 그 Lifecycle 객체가 destroy 상태가 되면 자동적으로 지워진다.

  • 정지된 엑티비티들때문에 Crash날 일이 없다.

    • 엑티비티가 백스택에 있을때와 같이, 옵저버의 생명주기가 비활성화 상태일 때는, 어떠한 LiveData이벤트도 받지 않는다.

  • 직접 생명주기를 핸들링할 필요가 없다.

    • UI 컴포넌트는 단지 연관된 데이터를 관찰하기만 하고, resume / stop을 신경쓸 필요가 없다. LiveData가 상태변화를 감지하여 알아서 관리해준다.

  • 항상 최신 데이터를 유지한다.

    • 생명주기가 비활성화 상태에서 활성화 상태로 변했을 때, UI 컴포넌트는 최신의 데이터를 받는다. 예를들어, 백그라운드에 있던 엑티비티가 다시 포그라운드가 되었을 때, 최신의 데이터를 받는다.

  • 구성(Configuration)이 변경되었을 때 적절하게 대응한다.

    • Activity나 Fragment가 구성변경되어 재생성될 때, 그 컴포넌트들은 LiveData로부터 즉시 사용가능한 최신데이터를 제공받는다.

  • 자원 공유

    • 싱글턴 패턴을 이용해 시스템 서비스를 래핑하여 LiveData객체가 공유될 수 있도록 확장할 수 있다. LiveData 오브젝트가 시스템 서비스에 한번 연결되면, 리소스가 필요한 모든 옵저버는 LiveData 객체를 볼 수 있다. 자세한 내용은 아래의 Extend LiveData항목을 참고한다.

LiveData 객체 사용하기

LiveData 객체를 사용하기 위해 다음의 절차를 수행한다.

  1. 특정 데이터를 유지할 LiveData 인스턴스를 생성한다. 이 작업은 주로 ViewModel 클래스 안에서 이루어진다.

  2. onChanged() 메서드를 정의하고 있는 Observer 인스턴스를 생성한다. onChanged()메서드는 LiveData가 유지하고 있는 데이터에 변화가 감지되었을 때 어떻게 동작할지를 제어하도록 구현한다. 대부분 Activity나 Fragment 같은 UI 컨트롤러에서 Observer 인스턴스를 생성한다.

  3. observe() 메서드를 Observer 인스턴스를 LiveData 인스턴스에 연결한다. observe 메서드는 LifecycleOwner 인스턴스를 받는다. 이는 Observer 인스턴스가 LiveData 인스턴스를 구독하도록 하여, 변화에 대해 알림을 받도록 한다. 일반적으로 Observer 인스턴스는 Activity나 Fragment 같은 UI 컨트롤러에 붙인다.

    Note : observeForever(Observer) 메소드를 이용하여 연관된 LifecycleOwner 인스턴스에 상관없이 옵저버를 등록할 수 있다. 이 경우, 옵저버는 항상 활성상태이고, 항상 변경사항에 알림을 받도록 간주된다. removeObserver(Observer) 메서드를 이용하여 등록된 옵저버를 제거할 수 있다.

LiveData객체에 저장된 값을 업데이트하면, 현재 붙어있는 활성상태의 LifecycleOwner들에게 트리거된다.

LiveData는 UI 컨트롤러의 옵저버가 변경사항을 구독하도록 할 수 있다. LiveData가 유지하고 있는 데이터가 바뀌면, UI는 자동적으로 화면을 갱신한다.

 

LiveData 객체 생성

LiveData는 List같은 Collections 구현체를 포함하여 모든 데이터와 함께 사용될 수 있는 래퍼 클래스이다. LiveData는 일반적으로 ViewModel 인스턴스 안에 저장되고, 아래의 예제처럼 Getter 메서드를 통해서 접근하도록 구현한다.

public class NameViewModel extends ViewModel {

    // Create a LiveData with a String
    private MutableLiveData<String> mCurrentName;

    public MutableLiveData<String> getCurrentName() {
        if (mCurrentName == null) {
            mCurrentName = new MutableLiveData<String>();
        }
        return mCurrentName;
    }

    // Rest of the ViewModel...
}

처음에는, LiveData 인스턴스 안의 실제 데이터는 저장되지 않는다.
Note : 다음과 같은 이유때문에 UI를 업데이트하는 LiveData 인스턴스는 Activity나 Fragment가 아닌 ViewModel에 저장되어야 한다.

  • Activity / Fragment 내부에 코드가 모이는 상황을 피하기 위해. - UI 컨트롤러는 데이터의 상태를 유지하는 역할을 몰라도 된다. 주어진 데이터를 잘 보여주는 역할만 수행하면 된다.

  • LiveData를 특정 Activity나 Fragment 인스턴스에 종속시키지 않고, 구성변경으로부터 LiveData 인스턴스가 살아있도록 하기 위함

LiveData 객체 관찰

대부분의 경우에, 앱 컴포넌트의 onCreate() 메서드가 LiveData의 관찰을 시작하기 적절한 위치이다. 그 이유는 다음과 같다.

  • onResume() 메서드와 같이 중복으로 호출되지 않음을 보장한다.
  • Activity나 Fragment가 활성화가 되자마자 화면을 표시할 ㄷ이터가 있는지를 확인할 수 있다. 앱 컴포넌트가 STARTED 상태가 되자마자, LiveData로부터 가장 최근의 데이터를 받는다. 이는 관찰할 LiveData가 설정되어 있는 경우에만 발생한다.

일반적으로, LiveData는 데이터의 변화가 있을 때에만, 활성화된 관찰자에게만 업데이트를 알린다. 이 동작의 예외케이스로는, 관찰자의 상태가 비활성에서 활성으로 바뀔 때 업데이트 알림을 받는다. 또한, 관찰자의 상태가 비활성화에서 활성화로 두번째 변경되면, 마지막 활성화 상태 이후로 값의 변경이 있을 때에만 업데이트 알림을 받는다.

다음의 샘플코드는 어떻게 LvieData의 관찰을 시작하는지 보여주고 있다.

 

public class NameActivity extends AppCompatActivity {

    private NameViewModel mModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Other code to setup the activity...

        // Get the ViewModel.
        mModel = ViewModelProviders.of(this).get(NameViewModel.class);

        // Create the observer which updates the UI.
        final Observer<String> nameObserver = new Observer<String>() {
            @Override
            public void onChanged(@Nullable final String newName) {
                // Update the UI, in this case, a TextView.
                mNameTextView.setText(newName);
            }
        };

        // Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
        mModel.getCurrentName().observe(this, nameObserver);
    }
}

nameObserver 인스턴스가 파라미터로 전달되어 observer()메서드가 호출된 후에, mCurrentName에 저장된 가장 최근값을 제공하기 위해 즉시 onChanged() 메서드가 호출될 것이다. 만약 mCurrentName에 LiveData가 설정되어 있지 않으면, onChanged() 메서드는 호출되지 않는다.

 

LiveData 객체 갱신

LiveData는 저장된 데이터를 갱신하기 위한 공개적으로 사용가능한 메서드가 없다. MutableLiveData 클래스는 공개적으로 setValue(T), postValue(T) 메서드를 노출하고, LiveData안에 저장된 데이터를 수정할 필요가 있다면, 반드시 저 메서드들만 이용해야 한다. 일반적으로 수정가능한 MutableLiveData는 ViewModel 내부에서 사용되고, ViewModel은 수정 불가능한 LiveData로 관찰자에게 노출한다.

옵저버를 연결한 후에, 다음의 예제와 같이 LiveData 인스턴스의 값을 변경할 수 있다.

 

mButton.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        String anotherName = "John Doe";
        mModel.getCurrentName().setValue(anotherName);
    }
});

이 예제에서 setValue(T) 메서드를 호출하면 관찰자들은 값이 바뀐 John Doe 로 onChanged() 메서드를 호출할 것이다. 이 예제에서는 버튼클릭을 보여줬지만, setValue() / postValue()는 네트워크 요청, 데이터베이스 조회 등 다양한 상황에서 데이터를 바꾸고 싶을 때 호출될 수 있다. setValue() / postValue() 메서드가 호출된 다음에는 관찰자를 트리거하여 UI를 갱신하도록 진행된다.
Note : 메인스레드에서 LiveData를 갱신하려면 반드시 setValue(T) 메서드를 호출해야 한다. 만약, 작업스레드에서 LiveData를 갱신하려면 postValue(T) 메서드를 호출해야 한다.

LiveData를 Room과 함꼐 사용하기

Room은 LiveData 인스턴스를 반환하여 관찰가능한 쿼리를 제공하는 DB 라이브러리이다. 관찰가능한 쿼리는 Database Access Object(DAO)의 파트로써 작성된다.

Room은 데이터베이스가 업데이트 될 때 LiveData객체를 업데이트하기 위한 모든 필요한 코드를 생성한다. 생성된 코드는 필요하다면 백그라운드 스레드에서 비동기로 쿼리를 실행한다. 이 패턴은 DB에 저장된 데이터와 UI를 동기화하여, 화면에 보여지는 데이터를 유지하는데 효율적이다.

 

LiveData 확장하기

관찰자의 상태가 STARTED / RESUMED 일때, LiveData는 관찰자를 활성 상태로 간주한다. 다음의 예제코드는 어떻게 LiveData 클래스가 확장되는지를 보여준다.

 

public class StockLiveData extends LiveData<BigDecimal> {
    private StockManager mStockManager;

    private SimplePriceListener mListener = new SimplePriceListener() {
        @Override
        public void onPriceChanged(BigDecimal price) {
            setValue(price);
        }
    };

    public StockLiveData(String symbol) {
        mStockManager = new StockManager(symbol);
    }

    @Override
    protected void onActive() {
        mStockManager.requestPriceUpdates(mListener);
    }

    @Override
    protected void onInactive() {
        mStockManager.removeUpdates(mListener);
    }
}

이 예제에서 price listener 구현은 다음의 중요한 메서드들에 포함되어 있다.

  • onActivity() 메서드는 LiveData 인스턴스가 활성 관찰자를 가지고 있을 때 호출된다. 이 예제에서는 stock 가격 갱신의 관찰을 이 메서드로부터 시작했다.
  • onInactive() 메서드는 LiveData 인스턴스가 어떤 활성화된 관찰자도 가지고있지 않을 때 호출된다. 관찰중인 관찰자가 없으므로, StockManager 서비스와 계속 연결을 유지할 이유가 없다.
  • setValue(T) 메서드는 LiveData 인스턴스의 값을 갱신하고, 변화에 대하여 활성 관찰자들에게 알려준다.

StockLiveData 클래스는 다음의 예제처럼 사용될 수 있다.

public class MyFragment extends Fragment {
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        LiveData<BigDecimal> myPriceListener = ...;
        myPriceListener.observe(this, price -> {
            // Update the UI.
        });
    }
}

 

observe() 메서드는 첫번째 인자로 Fragment를 받았다. 이렇게 함으로써 소유자와 관련된 Lifecycle 객체가 관찰자와 바인딩된다. 즉,

  • Lifecycle 객체가 활성상태가 아니면, 관찰자는 값이 변경되더라도 호출되지 않는다.
  • Lifecycle 객체가 파괴된 후에, 관찰자는 자동으로 제거된다.

LiveData 인스턴스가 라이프사이클을 인지할 수 있다는 사실은 여러 Activity, Fragment, Service 사이에서 공유될 수 있다는 것을 의미한다. 다음의 예제는 예제를 쉽게 유지하기 위해, LiveData 클래스를 싱글턴 패턴으로 구현했다.

 

public class StockLiveData extends LiveData<BigDecimal> {
    private static StockLiveData sInstance;
    private StockManager mStockManager;

    private SimplePriceListener mListener = new SimplePriceListener() {
        @Override
        public void onPriceChanged(BigDecimal price) {
            setValue(price);
        }
    };

    @MainThread
    public static StockLiveData get(String symbol) {
        if (sInstance == null) {
            sInstance = new StockLiveData(symbol);
        }
        return sInstance;
    }

    private StockLiveData(String symbol) {
        mStockManager = new StockManager(symbol);
    }

    @Override
    protected void onActive() {
        mStockManager.requestPriceUpdates(mListener);
    }

    @Override
    protected void onInactive() {
        mStockManager.removeUpdates(mListener);
    }
}

//Fragment에서 사용
public class MyFragment extends Fragment {
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        StockLiveData.get(getActivity()).observe(this, price -> {
            // Update the UI.
        });
    }
}

여러 Fragment / Activity들이 MyPriceListener인스턴스를 관찰할 수 있다. 하나 이상의 UI 컴포넌트가 화면에 보이고 활성화 상태라면, LiveData는 시스템 서비스에만 연결된다.

 

LiveData 변형

관찰자에게 이벤트가 전달되기 전에 저장된 값을 변경하거나, 다른 값을 기반으로 다른 LiveData 인스턴스를 리턴해야 할 필요가 있을 수도 있다. 이러한 시나리오를 지원하는 헬퍼 메서드를 가진 Transformations 클래스가 Lifecycle 패키지에 포함되어 있다.

Transformations.map() : LiveData 인스턴스 안에 저장된 값에 함수를 적용하고, 아래방향으로 결과를 전파한다.

LiveData<User> userLiveData = ...;
LiveData<String> userName = Transformations.map(userLiveData, user -> {
    user.name + " " + user.lastName
});

Transformations.switchMap() : map() 메서드와 비슷하게, LiveData 인스턴스 안에 저장된 값에 함수를 적용하고, 래핑을 풀고, 아래방향으로 결과를 전파한다. switchMap()에 전달되는 함수는 반드시 LiveData 인스턴스를 반환해야 한다.

 

private LiveData<User> getUser(String id) {
  ...;
}

LiveData<String> userId = ...;
LiveData<User> user = Transformations.switchMap(userId, id -> getUser(id) );

변환(transformation) 메서드를 사용하여 관찰자의 생명주기 전반에 걸쳐 정보를 전달 할 수 있다. 관찰자가 리턴된 LiveData 인스턴스를 보고있지 않으면, 변환 기능은 동작하지 않는다. 변환 계산은 느리므로, 생명주기 관련된 동작은 명시적으로 호출하거나 의존성이 없다면 암묵적으로 지나칠 것이다.

만약 ViewModel 인스턴스 안에 Lifecycle 인스턴스가 필요하다면, 변형이 더 좋은 해결책일 것이다. 예를들어, 주소를 받아서 우편번호를 반환하는 UI가 있다고 가정해보자. 다음의 예제처럼 간단한 ViewModel을 구현할 수 있다.

 

class MyViewModel extends ViewModel {
    private final PostalCodeRepository repository;
    public MyViewModel(PostalCodeRepository repository) {
       this.repository = repository;
    }

    private LiveData<String> getPostalCode(String address) {
       // DON'T DO THIS
       return repository.getPostCode(address);
    }
}

UI 컴포넌트는 getPostCode() 메서드가 불릴때마다 이전의 LiveData 인스턴스를 해제하고, 새로운 인스턴스를 등록해줄 필요가 있다. 게다가 UI 컴포넌트가 재생성되면, 이전 호출값을 사용하는 대신 **respository.getPostCode()**이 다시 트리거된다.

다음 예제는 위의 문제점을 해결하기 위해,변형 방법으로 주소를 받아 우편번호를 조회하는 것이다.

class MyViewModel extends ViewModel {
    private final PostalCodeRepository repository;
    private final MutableLiveData<String> addressInput = new MutableLiveData();
    public final LiveData<String> postalCode =
            Transformations.switchMap(addressInput, (address) -> {
                return repository.getPostCode(address);
             });

  public MyViewModel(PostalCodeRepository repository) {
      this.repository = repository
  }

  private void setInput(String address) {
      addressInput.setValue(address);
  }
}

이 예제에서는, postalCode 필드는 절대 변할 일이 없기때문에 public final 이다. postalCode필드는 addressInput 필드의 변형으로 정의되었는데, 이는 addressInput이 변할때마다 repository.getPostCode() 메서드가 호출되는 것을 의미한다. 현재 활성 관찰자가 있다면 정상동작할 것이고, ** repository.getPostCode()**메서드를 호출하는 그 때에 활성관찰자가 없다면 관찰자가 추가되기 전까지 어떠한 계산도 일어나지 않을 것이다.

이 메카니즘은 앱의 로우레벨단에서 상황에 따라 늦게 계산되는 LiveData 객체를 생성할 수 있도록 한다. ViewModel 객체는 쉽게 LiveData 인스턴스의 참조를 얻어서 그 위에 변형규칙을 적용할 수 있다.

새로운 변형 생성

앱에서 유용하게 적용할 수 있는 12개의 특정 변형들이 있지만, 기본적으로 제공되지는 않는다. 변형을 직접 구현하려면, 다른 LiveData 인스턴스를 들을 수 있고, 자신이 생성한 이벤트를 처리할 수 있는 MediatorLiveData 클래스를 이용해야 한다. MediatorLiveData는 원래의 LiveData 인스턴스로 상태를 정확하게 전달한다. 이 패턴을 더 배우려면, Transformations 클래스를 참고한다.

 

여러 LiveData를 병합하기

LiveData의 서브클래스인 MediatorLiveData는 여러개의 LiveData를 병합가능하도록 지원한다. MediatorLiveData 인스턴스의 관찰자는 원래의 LiveData 인스턴스들중 하나라도 변경될 때마다 트리거된다.

예를들어, 앱의 UI에 로컬 DB / 네트워크로부터 갱신될 수 있는 LiveData 인스턴스가 있다면, 다음과 같은 LiveData 소스들을 MediatorLiveData 객체에 추가할 수 있다.

  • 데이터베이스에 저장된 데이터와 관련된 LiveData 인스턴스
  • 네트워크로부터 받아오는 데이터와 관련된 LiveData 인스턴스

UI에서는 양쪽 소스로부터의 갱신알림을 방기 위해 MediatorLiveData 인스턴스만 관찰하면 된다.

 

간단한 예제

class UserProfileViewModel: ViewModel(){
  
      //MutableLiveData란 변경할 수 있는 LiveData 형입니다.
      //일반적인 LiveData형은 변경할 수 없고 오로지 데이터의 변경값만을 소비하는데 반해
      //MutableLiveData는 데이터를 UI Thread와 Background Thread에서 선택적으로 바꿀 수 있습니다.
      private val _post = MutableLiveDta<User>()
      
      //  _post로 선언된 MutableLiveData를 post를 통해 발행합니다.
      // 이렇듯 ViewModel에서만 _post를 변경할 수 있기때문에 보안에 더 좋습니다.
      val post :LiveData<Post>
          get() = _post
}

 

그럼 위와같은 데이터를 Activity에서 받으려면

 

class PostActivity():AppCompatActivity(){
  
  override fun onCreate(savedInstacneState:Bundle?){
    
    //조금전 ViewModel에서 post LiveData를 Observe합니다.
    //첫번째 인자는 UI이며 해당 인자로 어떤 UI Thread를 사용할지 결정합니다.
    //두번째는 Observe 콜백입니다.
    postViewModel.post.observe(this,
      Observer{
        post -> postTitle.text = post?.title
      }
    )
  }
}

 

LiveData 콜백을 실행하는 방법을 알아보겠습니다.

 

post.setValue(post)
post.postValue(post)

 

위와같이 MutableLiveDatasetValue 혹은 PostValue에서 실행하게되는데 두개의 차이점은 setValue에서는 UI ThreadMain Thread에서 실행하고 두번째는 Background Thread에서 처리합니다.

 

LiveData를 더 잘쓰려면 데이터바인딩!

 

<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
        <variable name="vm" type="MainViewModel" />
    </data>
.........

</layout>

 

Databinding에서 LiveData를 쓰면 더 편리합니다. 왜냐면 아까와같은 Observe 패턴을 이용해서 UI를 직접 변경해줄 필요 없이

<TextView
    .....
     android:text="@{viewmodel.post.title}"
     
</TextView>

아주 깔끔하게 선언할 수 있습니다. 이제 title이 변경되는대로 TextView UI는 알아서 변경이 됩니다.

그렇다면 LiveData Observer UI(Activity, Fragment)가 사라진다면? 더이상 새로운 데이터를 발행하지 않습니다 rx로 따지면 Dispose가 필요없습니다.

라이브데이터 변형하기

공문서에는.. Transformation이라고 하는데 어떻게 번역을 해야할지 난감하네요 변형하기라고 하겠습니다! 라이브데이터를 잘쓰긴 위해선 3가지만 기억하세요 북치기, 박치기,매치기가 아니라… map, switchmap, mediatorLiveData

 

Map

라이브데이터의 변경을 다른 라이브데이터에게 알려주는 메서드입니다.

val userLiveData:LiveData  = ...;
val userNameLLiveData  = Transformations.map(userLiveData, user -> {
     return user.firstName + " " + user.lastName; // String을 리턴합니다.
});

UserLiveData의 변경사항을 Observe해서 함수를 통해 원하는값으로 변경한뒤 ‘String’을 리턴합니다. 즉 새로운 LiveData를 리턴하는게 아닌 데이터만 변경합니다.

 

 

SwitchMap

SwitchMapLiveData를 변경사항을 받아서 다른 LiveData를 발행합니다. 일반적으로 RoomDatabaseLiveData로 쓸때 많이 사용합니다.

val userIdLiveData:MutableLiveData = ...;
val userLiveData:LiveData = Transformations.switchMap(userIdLiveData, id ->
    repository.getUserById(id)); // LiveData를 리턴합니다.

fun setUserId(userId:String) {
     this.userIdLiveData.setValue(userId);
}

 

SwitchMap은 데이터의 인자값에 따라 다른 LiveData를 발행합니다. repository.getUserById(id)RoomDatabase에서 ID값에 따라 유저값을 가져오며 return값이 LiveData입니다. SwitchMap을 잘보면 LiveData값을 리턴하고있습니다. 따라서 인자값에따라 다른 데이터소스를 보낼 수 있습니다.

 

MediatorLiveData

val liveData1:LiveData = ...;
val  liveData2: LiveData = ...;

val liveDataMerger:MediatorLiveData = new MediatorLiveData<>();
 liveDataMerger.addSource(liveData1, value -> liveDataMerger.setValue(value));
 liveDataMerger.addSource(liveData2, value -> liveDataMerger.setValue(value));

여러 데이터 소스를 한곳에서 Observe할때 사용을합니다. 예를들어 Fragment별로 LiveData<Error>가 있고 이걸 Activity 한곳에서 Crashlistic에 기록한다거나 Toast메세지를 띄울때 FragmentLiveDataActivityMediatorLiveData를 통해 사용할 수 있습니다.

마치며

LiveData를 그냥 LiveData만 쓰면 좋은점을 느끼기 힘든것같습니다 Databinding, ViewModel, RoomDatabase등과 함께쓸경우 그 진가가 발휘되며 10줄의 소스코드를 1~2줄로 바꾸는 위엄을 보여주게됩니다.

 

 

 

출처 : https://medium.com/harrythegreat/jetpack-android-livedata-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0-ed49a6f17de3

 

Jetpack Android — LiveData 알아보기

LiveData? 특이한 이름입니다. 살아있는 데이터? 네이밍을 어떻게 한건지는 모르겠지만 LiveCycle을 알고있는 DataType이라고하면 더 와닿을것같습니다. 그러면 LiveCycle을 알면 뭐가 좋은데?라는 생각이

medium.com

출처 : http://dktfrmaster.blogspot.com/2018/02/livedata.html

 

[안드로이드] Architecture Component 2 - LiveData 공식문서 번역

현업 개발자로써 삽질하는 과정을 기록하는 블로그입니다.

dktfrmaster.blogspot.com

 

'android' 카테고리의 다른 글

Android MVP  (0) 2020.03.10
Room 사용하기  (0) 2020.03.10
AsyncTask 란  (0) 2020.03.09
안드로이드 서비스 4가지 주요 컴포넌트  (0) 2020.03.06
안드로이드 생명주기  (0) 2020.03.06