我目前正在构建一个小型社交媒体风格的应用程序,该应用程序利用 RxJava 2 和 Firebase 。我正在使用MVP样式架构,并且我使用名为AuthSource的接口抽象出了我的AuthService。
为简单起见,我将在我的服务中使用Single方法:
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()。
- 如果我的理解是正确的,在这种情况下,create()是比使用fromCallable()更好的选择,因为fromCallable()应该用于同步事件(即不像Firebase API回调)?
- 它就像在Observable.create()中抛出我的异步回调一样简单吗?我很害怕这是多么容易......
答案 0 :(得分:5)
假设只是致电
CompositeDisposable.clear()
是否安全 当Presenter完成时,会处理我的垃圾收集吗? (假设我还没有在其余代码中创建内存泄漏)。
比这更棘手。如果Observable
引用的所有内容都属于Observable
范围,则非处置Activity
不会创建内存泄漏。生产者和消费者都将与Activity
一起进行垃圾收集。如果您引用的资源将在Activity
(例如Application
级别实例化的提供程序中继续存在,则可能会发生内存泄漏。因此,如果您想使用CompositeDisposable.clear()
,请确保在emitter.setCancellable()
内部实施Observable.create()
以处置这些漏洞资源。
如果我的理解是正确的,
create()
是更好的选择 在这种情况下,fromCallable()
应该用于fromCallable()
同步事件(即不像Firebase API回调)?
create()
用来命名为fromAsync()
。在包装回调代码时,使用fromCallable()
包装同步方法调用create()
。
是否真的像在我的异步回调中抛出一样简单
Observable.create()
?我很害怕这很容易......
如果您在第一点提到的范围之外处理那些讨厌的引用,那就简单了。
通常在Android上,内存泄漏涉及Context
,这很大。一定要测试你的代码。 leakcanary对此事有很大的帮助。
最后,您可以使用现有的Firebase RxJava绑定来避免自行包装。或者从他们那里获取灵感:
答案 1 :(得分:1)
调用clear将从Observable中分离订阅者 - 对发出的事件作出反应的代码,结果是由演示者/活动包含并且有硬参考的订阅者将不再由观察者持有并且比演示者/活动生命周期更长寿 但是,请注意,如果您的Observable本身包含对您的演示者/活动的引用,您仍然可能导致泄漏 在任何一种情况下,当您通过静态引用您的活动/演示者或其他比您的活动/演示者更长的对象(例如应用程序)上下文时,都会发生泄漏。
实际上,create()方法是从异步方法创建Observable的正确方法(BTW,在RxJava1中,有一种不同的过时方式也称为create,但它在RxJava2中被更改,因此会有没有办法错误地创建Observable,但这是一个不同的故事)
嗯,你仍然需要确保你服从Observable contract, 确保会有终端事件(onComplete / onError), 在终端事件(onCompleted / onError)和背压(使用Flowable Observable强制执行)之后将没有onNext