Должен ли я отказаться от подписки на завершенные наблюдаемые?

Если наблюдаемое завершено, мне еще нужно отказаться от подписки/распоряжаться (в RxJava2) наблюдаемым, чтобы удалить Observer (предотвратить утечку памяти) или обрабатывается внутри RxJava после события onComplete или onError?

как насчет других типов, таких как Single, Completable, Flowable и т.д.

Ответ 1

Да, вы правы.

После прекращения потока (onComplete/onError вызывается) абонент автоматически отписывается. Вы должны проверить эти поведения с помощью метода isUnsubscribed() объекта Subscription.

Ответ 2

Хотя вам не нужно вручную отписываться от прекращенного потока, вы все равно можете создать утечку памяти, используя RxJava2, если не будете осторожны.

Рассмотрим следующий код:

repository.getData()
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(data -> myTextView.setText(data.toString()));

Лямбда-параметр в подписке - "синтетический сахар" над анонимным внутренним классом:

subscribe(new Consumer<Data>() {
    @Override
    public void accept(final Data data) {
        myTextView.setText(data.toString());
    }
});

В JVM анонимный внутренний класс поддерживает ссылку на внешний класс.

Предположим, что для приведенного выше наивного кода внешним классом является Activity (это также следует для Fragment, Service, BroadcastReceiver или любого класса, жизненный цикл которого контролируется ОС Android).

Активность подписывается на Observer, но затем уничтожается ОС Android в условиях нехватки памяти (вы можете имитировать этот эффект, включив "Параметры разработчика"/"Не сохранять действия"). Если работа над Schedulers.io() все еще выполняется, когда действие уничтожено, ссылка на действие будет по-прежнему сохраняться через анонимный внутренний класс. Это означает утечку памяти, которая препятствует завершению Activity сборщиком мусора. Если у Activity есть несколько видов или, скажем, объект Bitmap, то утечка памяти может быть весьма существенной.

Здесь есть несколько решений, но одно из них заключается в том, чтобы поддерживать объект CompositeDisposable и очистить его в методе жизненного цикла onDestroy() действия Android:

public class MyActivity extends Activity {

   DataRepository dataRepository;
   CompositeDisposable disposables;

   @Override
   public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       disposables = new CompositeDisposable();
   }

   public void onButtonClick(View v) {
       repository.getData()             
          .subscribeOn(Schedulers.io())
          .observeOn(AndroidSchedulers.mainThread())
          .doOnSubscribe(disposable -> disposables.add(disposable))
          .subscribe(data -> myTextView.setText(data.toString()));
   }

   @Override
   public void onDestroy() {
       disposables.clear();
       super.onDestroy();
   }
}

Вы можете сослаться на хороший пример того, как использовать RxJava в приложении для Android, в официальных чертежах архитектуры Android Google.