【问题标题】:Proper usage of Observable.create() in RxJava 2 (Best Practices)在 RxJava 2 中正确使用 Observable.create()(最佳实践)
【发布时间】:2017-02-14 18:37:37
【问题描述】:

我目前正在构建一个利用 RxJava 2Firebase 的小型社交媒体风格应用程序。我正在使用 MVP 风格的架构,并且我已经使用一个名为 AuthSource 的接口抽象出了我的 AuthService。

为简单起见,我将在我的服务中使用单一方法:

public class FirebaseAuthService implements AuthSource {

private FirebaseAuth auth;
private FirebaseAuth.AuthStateListener listener;

//initialization code

@Override
public Maybe<User> getUser() {
    return Maybe.create(new MaybeOnSubscribe<User>() {
                            @Override
                            public void subscribe(final MaybeEmitter<User> e) throws Exception {
                                if (auth == null) {
                                    auth = FirebaseAuth.getInstance();
                                }

                                if (listener != null) {
                                    auth.removeAuthStateListener(listener);
                                }

                                listener = new FirebaseAuth.AuthStateListener() {
                                    @Override
                                    public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
                                        FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
                                        auth.removeAuthStateListener(listener);
                                        if (firebaseUser != null) {
                                            User user = new User(
                                                    firebaseUser.getDisplayName(),
                                                    firebaseUser.getEmail());

                                            user.setUserId(firebaseUser.getUid());


                                            Uri photoUrl = firebaseUser.getPhotoUrl();
                                            if (photoUrl != null){
                                                user.setProfilePhotoUrl(photoUrl.toString());
                                            }
                                            e.onSuccess(user);
                                        } else {
                                            e.onComplete();
                                        }
                                    }
                                };

                                auth.addAuthStateListener(listener);
                            }
                        }
    );

}

}

interface AuthSource {
    Maybe<User> getUser();
//Other methods etc.
}

最后,我将展示处理调用的 Presenter 方法:

//from with a Presenter:
@Override
private void getUserData() {
    disposableSubscriptions.add(
            auth.getUser().subscribeOn(schedulerProvider.io())
                    .observeOn(schedulerProvider.ui())
                    .subscribeWith(
                            new DisposableMaybeObserver<User>() {

                                @Override
                                public void onError(Throwable e) {
                                    view.makeToast(R.string.error_retrieving_data);
                                    view.startDispatchActivity();
                                }

                                @Override
                                public void onComplete() {

                                }

                                @Override
                                public void onSuccess(User user) {
                                    ProfilePagePresenter.this.currentUser = user;
                                    view.setName(user.getName());
                                    view.setEmail(user.getEmail());
                                    if (user.getProfilePhotoUrl().equals("")) {
                                        view.setDefaultProfilePhoto();
                                    } else {
                                        view.setProfilePhotoURI(user.getProfilePhotoUrl());
                                    }

                                    getUserProfileFromDatabase();

                                }
                            }
                    )
    );
}

我意识到这个问题的主题有点笼统,所以我会尝试从这里缩小范围。我在上面发布的代码有效,因为我使用 Create() 成功地从 Firebase 的 API 获取数据。问题是,我对使用 RxJava 2 还很陌生,而且我不确定垃圾收集和内存泄漏的幕后情况。根据 RxJava 2 Docs,我选择使用 Observable.create():

“提供一个 API(通过冷的 Observable)将反应式世界与回调式世界连接起来。”

RxJava 2 Docs 最后,我目前处理这些 Observable 的唯一主动措施是,当事件将用户带到新的 Activity 时,在我的 Presenter 中调用 CompositeDisposable.clear()。


问题:

- 假设在 Presenter 完成时简单地调用 CompositeDisposable.clear() 是否可以安全地处理我的垃圾收集? (假设我没有在其余代码中创建内存泄漏)。

-如果我的理解是正确的,在这种情况下 create() 是比 fromCallable() 更好的选择,因为 fromCallable() 应该用于同步事件(即不是像 Firebase API 回调这样的东西)?

-真的像在 Observable.create() 中抛出我的异步回调一样简单吗?我害怕这样做是多么容易......

【问题讨论】:

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


    【解决方案1】:

    假设简单地调用CompositeDisposable.clear() 是否安全? Presenter 结束后,会处理我的垃圾收集吗? (假设我没有在其余代码中创建内存泄漏)。

    这比这有点棘手。如果Observable 引用的所有内容都属于Activity 范围,则未处置的Observable 不会造成内存泄漏。生产者和消费者都将与Activity 一起被垃圾收集。如果您引用的资源将在Activity 中存在,则可能会发生内存泄漏,例如在Application 级别实例化的提供程序。因此,如果您想使用CompositeDisposable.clear(),请确保在Observable.create() 中实现emitter.setCancellable() 以处理那些泄漏的资源。

    如果我的理解是正确的,create() 是一个更好的选择 比fromCallable() 在这种情况下,fromCallable() 应该用于 同步事件(即不像 Firebase API 回调)?

    create() 被命名为fromAsync()。使用fromCallable() 包装同步方法调用,包装回调代码时使用create()

    真的就像把我的异步回调扔进去一样简单吗 Observable.create()?我害怕这样做是多么容易......

    这很容易......如果您在第一点提到的范围之外处理那些讨厌的引用。

    通常在 Android 上,内存泄漏涉及 Context,这是很大的。一定要测试你的代码。 leakcanary 对这件事情有很大的帮助。

    最后,您可以通过使用现有的 Firebase RxJava 绑定来避免自己进行包装。或者从他们那里获得灵感:

    【讨论】:

      【解决方案2】:
      • 调用 clear 将分离订阅者 - 对发出的事件做出反应的代码从 Observable 中分离出来,因此被演示者/活动包围并且硬引用它的订阅者将不再由观察者持有并且比演示者/活动的生命周期更长。
        但是,请注意,如果您的 Observable 本身包含对您的演示者/活动的引用,您仍然可能导致泄漏。
        在任何一种情况下,当您通过 static 或其他比您的 Activity/Presenter 存在于更长(例如应用程序)上下文中的对象引用您的 Activity/Presenter 时,都会发生泄漏。

      • 确实,create() 方法是从 async 方法创建 Observable 的正确方法(顺便说一句,在 RxJava1 中,有一种不同的过时方法称为也创建,但在 RxJava2 中进行了更改,所以会有没有办法错误地创建 Observable,但那是另一回事)

      • 好吧,你仍然需要确保你遵守Observable contract, 确保会有终端事件(onComplete/onError), 终端事件(onCompleted/onError)和背压(使用 Flowable Observable 强制执行)后不会有 onNext

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-26
        • 1970-01-01
        • 2011-06-16
        • 2018-07-25
        相关资源
        最近更新 更多