[android] MVVM – 11. Use RxLifecycle in ViewModel

Rx 가 비동기로 동작하다보니, 앱이 완전히 종료해야 동작이 끝나는 경우가 있다.

Observable.interval(0, 1, TimeUnit.SECONDS)
          .map(String::valueOf)
          .subscribe(second -> Log.i("###", second));

이 코드를 실행하면 back 버튼을 눌러서 앱을 종료해도 계속 로그가 찍힌다.

 

그래서 나온 것이 바로 https://github.com/trello/RxLifecycle

 

build.gradle 에 추가하고

compile 'com.trello.rxlifecycle2:rxlifecycle-android:2.1.0'
compile 'com.trello.rxlifecycle2:rxlifecycle-components:2.0.1'

 

그 후에 RxAppCompatActivityRxFragment 를 상속받은 후에

public class MyActivity extends RxAppCompatActivity {
.
.
.
}

 

.compose(bindToLifecycle())를 추가한다.

Observable.interval(0, 1, TimeUnit.SECONDS)
          .compose(bindToLifecycle())
          .map(String::valueOf)
          .subscribe(second -> Log.i("###", second));

이러면 아까처럼 back  버튼으로 앱을 종료하면 로그도 멈춘다.

 

하지만 뷰모델에서도 Rx를 써야하는데 bindToLifeCycle() 을 그냥 쓸 수는 없다. 남들은 어떻게하나 싶었는데, 생각보다 잘 안 나와서 걱정하던 중에 RxAppCompatActivity 코드를 보니 답이 있었다.

그걸 적용해서 BaseViewModel을 이렇게 바꾸면 된다.

import android.databinding.BaseObservable;

import com.trello.rxlifecycle2.LifecycleProvider;
import com.trello.rxlifecycle2.LifecycleTransformer;
import com.trello.rxlifecycle2.RxLifecycle;
import com.trello.rxlifecycle2.android.ActivityEvent;
import com.trello.rxlifecycle2.android.RxLifecycleAndroid;

import io.reactivex.Observable;
import io.reactivex.annotations.NonNull;
import io.reactivex.subjects.BehaviorSubject;

public class BaseViewModel extends BaseObservable implements LifecycleProvider<ActivityEvent> {
  private final BehaviorSubject<ActivityEvent> lifecycleSubject = BehaviorSubject.create();

  @NonNull
  @Override
  public Observable<ActivityEvent> lifecycle() {
    return lifecycleSubject.hide();
  }

  @NonNull
  @Override
  public <T> LifecycleTransformer<T> bindUntilEvent(ActivityEvent event) {
    return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
  }

  @NonNull
  @Override
  public <T> LifecycleTransformer<T> bindToLifecycle() {
    return RxLifecycleAndroid.bindActivity(lifecycleSubject);
  }

  public void onCreate() {
    lifecycleSubject.onNext(ActivityEvent.CREATE);
  }

  public void onResume() {
    lifecycleSubject.onNext(ActivityEvent.RESUME);
  }

  public void onPause() {
    lifecycleSubject.onNext(ActivityEvent.PAUSE);
  }

  public void onDestroy() {
    lifecycleSubject.onNext(ActivityEvent.DESTROY);
  }
}

 

대신 Activity의 onDestroy()에서 뷰모델의 onDestroy()를 반드시 호출해줘야 정상동작한다.

public class MyActivity extends AppCompatActivity {
  MyActivityModel myActivityModel = new MyActivityModel();

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
    binding.setModel(myActivityModel);

    myActivityModel.onCreate();
  }

  @Override
  protected void onResume() {
    super.onResume();
    myActivityModel.onResume();
  }

  @Override
  protected void onPause() {
    super.onPause();
    myActivityModel.onPause();
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    myActivityModel.onDestroy();
  }
}