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.