2017-01-24 1 views
12

Si un observable se termine, dois-je encore désabonnement/éliminer (dans RxJava2) l'observable pour supprimer l'observateur (prévenir les fuites de mémoire) ou est-il géré en interne par RxJava une fois un événement onComplete ou onError se produit?Dois-je me désinscrire de l'observable complet?

ce que d'autres types comme Single, Completable, Flowable etc.

Répondre

10

Oui, vous avez raison.

Après la fin d'un flux (onComplete/onError a été appelé), l'abonné se désabonne automatiquement. Vous devriez être en mesure de tester ces comportements en utilisant la méthode isUnsubscribed() sur l'objet Abonnement.

0

Bien que vous n'ayez pas besoin de vous désabonner manuellement d'un flux terminé, vous pouvez toujours créer une fuite de mémoire en utilisant RxJava2 si vous ne faites pas attention.

Consultez le code suivant:

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

Le paramètre lambda dans la souscription est du « sucre syntactique » sur une classe interne anonyme:

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

Sur la machine virtuelle Java, une classe interne anonyme maintient une référence à la classe externe. Supposons que pour le code naïf ci-dessus, la classe externe soit une activité (cela s'applique également à un fragment, un service, un récepteur de diffusion ou à toute classe dont le cycle de vie est contrôlé par le système d'exploitation Android). L'activité s'abonne à l'Observateur, mais elle est ensuite détruite par le système d'exploitation Android dans des conditions de faible mémoire (vous pouvez imiter cet effet en activant Options du développeur/Ne pas conserver les activités). Si le travail sur Schedulers.io() est toujours en cours d'exécution lorsque l'activité est détruite, une référence sera toujours conservée pour l'activité via la classe interne anonyme. Cela signifie une fuite de mémoire qui empêche l'activité d'être finalisée par le garbage collector. Si l'activité a un certain nombre de vues ou, disons, un objet Bitmap, la fuite de mémoire peut être assez importante.

Il y a un certain nombre de solutions ici, mais l'un d'entre eux est de maintenir un objet CompositeDisposable et pour effacer ce dans la méthode du cycle de vie onDestroy() de l'activité 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(); 
    } 
} 

Vous pouvez vous référer à un bon exemple de comment utiliser RxJava dans une application Android dans le Google Android Architecture Blueprints officiel.