2017-01-24 3 views
12

Wenn eine Observable abgeschlossen ist, muss ich noch die Subskription abbestellen (in RxJava2), um den Observer zu entfernen (Speicherlecks zu verhindern) oder wird dies intern von RxJava behandelt, sobald ein onComplete oder onError Ereignis eintritt?Muss ich mich von der abgeschlossenen Observablen abmelden?

was ist mit anderen Arten wie Single, Completable, Flowable usw.

Antwort

10

Ja, Sie richtig sind.

Nachdem ein Stream beendet wurde (OnComplete/onError wurde aufgerufen), wird der Abonnent automatisch abgemeldet. Sie sollten diese Verhaltensweisen mit der Methode isUnsubscribed() für das Subskriptionsobjekt testen können.

0

Während Sie sich nicht manuell von einem beendeten Stream abmelden müssen, können Sie dennoch mit RxJava2 ein Speicherleck erstellen, wenn Sie nicht vorsichtig sind.

Betrachten Sie den folgenden Code ein:

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

Die Lambda-Parameter in der Zeichnung ist "syntaktischer Zucker" über eine anonyme innere Klasse:

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

Auf der JVM eine anonyme innere Klasse unterhält einen Verweis auf die äußere Klasse.

Angenommen, für den obigen naiven Code ist die äußere Klasse eine Aktivität (dies würde auch für ein Fragment, Service, BroadcastReceiver oder jede Klasse folgen, deren Lebenszyklus vom Android OS gesteuert wird).

Die Aktivität abonniert den Observer, wird dann jedoch durch das Android-Betriebssystem unter Bedingungen mit geringem Arbeitsspeicher zerstört (Sie können diesen Effekt nachahmen, indem Sie Entwickleroptionen aktivieren/Aktivitäten nicht beibehalten). Wenn die Arbeit an Schedulers.io() noch ausgeführt wird, wenn die Aktivität zerstört wird, wird weiterhin eine Referenz für die Aktivität über die anonyme innere Klasse verwaltet. Dies bedeutet ein Speicherleck, das verhindert, dass die Aktivität vom Garbage Collector abgeschlossen wird. Wenn die Aktivität eine Anzahl von Ansichten oder, sagen wir, ein Bitmap-Objekt aufweist, kann das Speicherleck ziemlich beträchtlich sein.

Es gibt eine Reihe von Lösungen, die hier aber einer von ihnen ist ein CompositeDisposable Objekt zu erhalten und diese der Android-Aktivität im onDestroy() Lifecycle-Methode zu löschen:

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(); 
    } 
} 

Sie auf ein gutes Beispiel verweisen kann wie man RxJava in einer Android App im offiziellen Google Android Architecture Blueprints verwendet.

Verwandte Themen