Когда отменить подписку на подписку

23

У меня вопрос о том, как отменить подписку на наблюдаемые. У меня есть два кода, и я не уверен, что лучше.

Пример 1 - & gt; Отменить подписку подписчика после завершения потока:

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 - & gt; Отменить подписку после того, как действие будет уничтожено:

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.

Какой из них лучше?

Заранее спасибо

    
задан MarcForn 02.03.2016 в 20:55
источник
  • У меня возникают проблемы с получением моего кода (с приложением для обновления), чтобы обновить второй раз при использовании pull для обновления прослушивателя. Я проверял, что мое приложение для обновления работает правильно, но второй набор «observable.subscribeOn (Schedulers.newThread ()) .Обратите внимание (AndroidSchedulers.mainThread ()). Subscribe (подписчик)« не работает, только первый. Есть идеи? –  lawonga 01.06.2016 в 04:02

3 ответа

23

Из двух вариантов лучше второй.

В вашем первом примере вы unsubscribing в методе onComplete() , который не нужен. Если вы достигнете onComplete() подписки, вы больше не обязаны отписывать ее.

Ваш второй пример правильный. Идея CompositeSubscription заключается в том, что вы можете добавить к ней несколько Subscriptions , а затем очистить ( unsubscribe ) сразу. Другими словами, это просто избавляет вас от необходимости хранить список Subscriptions , от которого вам нужно отказаться от подписки.

Одна сложная часть, использующая CompositeSubscription , состоит в том, что если вы однажды unsubscribe , вы можете НЕ использовать ее снова. Вы можете проверить документацию для метода compositeSubscription.add () для деталей почему. Короче говоря - он будет напрямую отменить подписку, которую вы хотите добавить. Это было преднамеренное решение (вы можете больше узнать об этом ЗДЕСЬ ).

Возвращаясь к вашему примеру, вызов unsubscribe() в onDestroy() активности прекрасен и избавит вас от утечек памяти. Что касается вашего комментария, что проблемы возникают, когда вы вызываете свой метод test() несколько раз - я бы сказал, что ваша проблема находится где-то в другом месте. Возможно, ваш случай использования не должен позволять называть его несколько раз, может быть, вам нужно очистить старые данные перед использованием недавно полученного и т. Д. Возможно, если вы подробно объясните, с какими проблемами вы столкнетесь, мы можем помочь больше. Но что касается CompositeSubscription - вы используете его и отменяете от него правильно!

    
ответ дан Vesko 02.03.2016 в 23:43
  • , но onDestroy не гарантируется. Означает ли это, что если onDestroy не вызван, по какой-то причине возникает утечка памяти, потому что отказ от подписки также не вызывается в этом случае? –  Stan Mots 18.12.2016 в 16:54
  • Поскольку ваш Observable испускает только один элемент, почему бы не использовать Single вместо этого? Вместо onNext () он вызывает однопользовательский onSuccess () один раз, а затем он выполняется (вызова onComplete () нет). –  Robert Lewis 07.02.2018 в 07:16
26

Нет необходимости отписываться в onCompleted . Взгляните на Наблюдаемый контракт

  

Когда Observable выдает уведомление OnError или OnComplete   наблюдателей, это заканчивает подписку. Наблюдателям не нужно выпускать   уведомление об отказе подписки для завершения подписки, завершаемой   Наблюдается таким образом.

С другой стороны, вы обязательно должны отказаться от подписки в onDestroy , чтобы предотвратить утечку памяти.

    
ответ дан MyDogTom 02.03.2016 в 21:18
4

Я думаю, это зависит от ваших потребностей. Если активность не будет ждать каких-либо других вызовов, я полагаю, вы могли бы отказаться от подписки внутри onCompleted ().

Я всегда отписываюсь в onDestroy ()

@Override
protected void onDestroy() {
    super.onDestroy();

    if (subscription != null) {
        subscription.unsubscribe();
    }
}

EDIT: посмотрите Ссылка

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();
}
    
ответ дан Matias Elorriaga 02.03.2016 в 21:04
  • В примере 2 вы должны объявить как можно больше подписчиков (переменных-членов) в качестве тех, которые вы используете в своей деятельности, а в Destroy отменить подписку на них, верно? –  MarcForn 02.03.2016 в 21:11
  • @MarcForn проверить мое редактирование –  Matias Elorriaga 02.03.2016 в 21:20
  • В моем проекте я использую CompositeSubscription, и внутри метода тестирования я добавляю подписку на CompositeSubscription. Проблема, которую я обнаружил (и это причина сообщения), заключается в вызове метода тестирования несколько раз. Сделав это, я понял, что у нас есть n подписка (то же самое), добавленная в список CompositeSubscription. –  MarcForn 02.03.2016 в 21:27
  • @MarcForn извините, я не понимаю .. вы хотите отредактировать сообщение и объяснить проблему с тестированием? может быть, я могу помочь –  Matias Elorriaga 02.03.2016 в 21:29
  • Да, отредактировано: Проблема возникает, когда я вызываю несколько раз метод тестирования, например, вызывается в «pull to refresh». Таким образом, CompositeSubscription становится все больше и больше. Как бы вы отменили подписку на это правильно? –  MarcForn 02.03.2016 в 21:58