RxJava2未在MVVM架构内执行链

时间:2018-10-30 15:42:14

标签: android performance mvvm rx-java rx-java2

我们在LoginViewModel中获得了以下代码:

private MutableLiveData<Response> loginLiveData;

@Inject
public LoginViewModel(LoginUseCase loginUseCase) {
    loginLiveData = new MutableLiveData<>();
    this.loginUseCase = loginUseCase;
}
@Override
public void onAttached() {
    checkHasToken();
}

public void checkHasToken() {
    add(loginUseCase.hasToken()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .doOnComplete(() -> Timber.d("doOnComplete"))
            .doFinally(() -> Timber.d("doFinally"))
            .doOnDispose(() -> Timber.d("doOnDispose"))
            .doOnTerminate(() -> Timber.d("doOnTerminate"))
            .doOnError(Timber::d)
            .doOnSubscribe(disposable -> Timber.d("doOnSubscribe " + disposable.isDisposed()))
            .subscribe(
                    () -> {
                        loginLiveData.setValue(Response.success());
                        Timber.d("Subscribe completable");
                    },
                    t -> {
                        loginLiveData.setValue(Response.error(t));
                        Timber.d("Subscribe error");
                    }
            )
);
}

hasToken()只是在SharedPreferences中检查令牌是否存在:

public Completable hasToken() {
    return !TextUtils.isEmpty(rawToken()) ? Completable.complete() : Completable.error(new Throwable("TokenIsEmpty");
}

代码成功运行,如日志所示:

D/LoginViewModel: doOnSubscribe false
D/LoginViewModel: doOnComplete
D/LoginViewModel: doOnTerminate
D/LoginViewModel: Subscribe completable
D/LoginViewModel: doFinally

尽管如此,几次却什么也不执行,日志如下所示:

D/LoginViewModel: doOnSubscribe false

仅此而已! 屏幕停留在这一点上,并且不进行进一步的逻辑处理。 它也发生在其他屏幕上。

我的基础ViewModel如下:

public abstract class AbsViewModel extends AndroidViewModel {

private static CompositeDisposable disposables;

public AbsViewModel(@NonNull Application application) {
    super(application);
}
public AbsViewModel() {
    super(null);
}

public void onAttached() {}

@Override
public void onCleared() {
    dispose();
    super.onCleared();
}

public static void add(Disposable disposable) {
    getCompositeDisposable().add(disposable);
}

protected void dispose() {
    disposables.dispose();
    disposables.clear();
}

public static void dispose() {
    Timber.d("dispose");
    getCompositeDisposable().dispose();
}

private static CompositeDisposable getCompositeDisposable() {
    if (disposables == null || disposables.isDisposed()) {
        disposables = new CompositeDisposable();
    }
    return disposables;
}

寻求帮助,因为该链仅被订阅,无法进一步执行。

1 个答案:

答案 0 :(得分:1)

您在static CompositeDisposable disposables中有AbsViewModel是造成这种奇怪行为的原因。这样做不是个好主意,因为ViewModel的所有实例都可以访问disposables相同实例-可以dispose()并重新创建它。

让我们看一个例子:我们有2个屏幕,分别带有ViewModel(从AbsViewModel扩展)。从第一个屏幕切换到第二个屏幕并返回到第一个屏幕时,将获得下一个跟踪:

  1. Screen1 ViewModel.attach()
  2. Screen2 ViewModel.attach()
  3. Screen1 ViewModel.attach()
  4. 屏幕1 ViewModel.onCleared()触发disposables.dispose()

在这种情况下,您将在步骤(3)中重新创建disposables并添加新的,但是在下一步(4)中,您将立即处理它。

这只是可能的情况之一,它指出了static的所有实例之间共享的AbsViewModel一次性用品的问题。如果您从static中删除disposables修饰符,并且使用所有修饰符,您的问题将消失。