Когда отменить подписку на подписку
У меня вопрос о том, как отменить подписку на наблюдаемые. У меня есть два кода, и я не уверен, что лучше.
Пример 1 → Отменить подписку подписчика после завершения потока:
Subscriber<String> subscriber = new Subscriber<String>() {
@Override
public void onCompleted() {
progressdialog.dissmiss();
unsubscribe();
}
@Override
public void onError(Throwable e) {
progressdialog.dissmiss();
}
@Override
public void onNext(String s) {
// do something with data
}
}
Пример 2 → Отменить подписку после уничтожения активности:
private void test(){
Subscriber<String> subscriber = new Subscriber<String>() {
@Override
public void onCompleted() {
progressdialog.dissmiss();
}
@Override
public void onError(Throwable e) {
progressdialog.dissmiss();
}
@Override
public void onNext(String s) {
// do something with data
}
};
subscription = BackendRequest.login(loginRequest)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriber);
compositeSubscription.add(subscription);
}
@Override
protected void onDestroy() {
super.onDestroy();
this.subscription.unsubscribe();
}
Я должен упомянуть, что мои наблюдаемые будут выдаваться только один раз, активность не должна ждать больше вызовов от Observable.
Какой из них лучше?
Заранее спасибо
Ответы
Ответ 1
Из двух вариантов лучше второй.
В вашем первом примере вы unsubscribing
в методе onComplete()
, который не нужен. Если вы достигнете onComplete()
подписки, вы больше не обязаны отменить подписку на нее.
Ваш второй пример правильный. Идея CompositeSubscription
заключается в том, что вы можете добавить к ней несколько Subscriptions
, а затем очистить (unsubscribe
) сразу. Другими словами, это просто избавляет вас от необходимости хранить список Subscriptions
, который вам нужно отменить.
Одна сложная часть с использованием CompositeSubscription
заключается в том, что если вы однажды unsubscribe
, вы можете НЕ использовать ее снова. Вы можете проверить документацию для метода compositeSubscription.add() для деталей. Короче говоря - он будет напрямую отменить подписку, которую вы хотите добавить. Это было преднамеренное решение (вы можете больше узнать об этом ЗДЕСЬ).
Возвращаясь к вашему примеру, вызов unsubscribe()
в onDestroy()
из Activity прекрасен и избавит вас от утечек памяти. Что касается вашего комментария о том, что проблемы возникают при многократном вызове метода test()
- я бы сказал, что ваша проблема находится где-то в другом месте. Возможно, ваш случай использования не должен позволять называть его несколько раз, может быть, вам нужно очистить старые данные перед использованием недавно полученного и т.д. Возможно, если вы подробно объясните, с какими проблемами вы столкнетесь, мы можем помочь больше. Но что касается CompositeSubscription
- вы используете его и отписываете от него правильно!
Ответ 2
Нет необходимости отписываться в onCompleted
. Взгляните на Наблюдаемый контракт
Когда Observable выдает уведомление OnError или OnComplete наблюдателей, это заканчивает подписку. Наблюдателям не нужно выпускать уведомление об отказе подписки для завершения подписки, завершаемой Наблюдается таким образом.
С другой стороны, вы обязательно должны отказаться от подписки в onDestroy
, чтобы предотвратить утечку памяти.
Ответ 3
Я думаю, это зависит от ваших потребностей. Если активность не будет ждать каких-либо других вызовов, я полагаю, вы могли бы отказаться от подписки внутри onCompleted().
Я всегда отписываюсь в onDestroy()
@Override
protected void onDestroy() {
super.onDestroy();
if (subscription != null) {
subscription.unsubscribe();
}
}
EDIT: посмотрите http://reactivex.io/RxJava/javadoc/rx/subscriptions/CompositeSubscription.html
private CompositeSubscription mCompositeSubscription = new CompositeSubscription();
private void doSomething() {
mCompositeSubscription.add(
AndroidObservable.bindActivity(this, Observable.just("Hello, World!"))
.subscribe(s -> System.out.println(s)));
}
@Override
protected void onDestroy() {
super.onDestroy();
mCompositeSubscription.unsubscribe();
}