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'
그 후에 RxAppCompatActivity
나 RxFragment
를 상속받은 후에
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(); } }