java2 - rxjava introduction
¿Tengo que cancelar la suscripción de observable completado? (2)
Sí, estás en lo correcto.
Una vez que se termina una transmisión (se ha llamado onComplete / onError), el suscriptor se cancela automáticamente. Debería poder probar estos comportamientos utilizando el método isUnsubscribed()
en el objeto Subscription.
Si un observable se completa, ¿todavía tengo que cancelar la suscripción / eliminar (en RxJava2) el observable para eliminar el observador (evitar pérdidas de memoria) o es manejado internamente por RxJava una vez que ocurre un evento onComplete
o onError
?
¿Qué pasa con otros tipos como Single
, Completable
, Flowable
etc.
Si bien no es necesario que cancele la suscripción manualmente de una secuencia terminada, puede crear una pérdida de memoria utilizando RxJava2 si no tiene cuidado.
Considere el siguiente código:
repository.getData()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(data -> myTextView.setText(data.toString()));
El parámetro lambda en la suscripción es "azúcar sintética" sobre una clase interna anónima:
subscribe(new Consumer<Data>() {
@Override
public void accept(final Data data) {
myTextView.setText(data.toString());
}
});
En la JVM, una clase interna anónima mantiene una referencia a la clase externa.
Supongamos que para el código ingenuo anterior, la clase externa es una Actividad (esto también se aplicaría a un Fragmento, Servicio, BroadcastReceiver o cualquier clase cuyo ciclo de vida esté controlado por el sistema operativo Android).
La Actividad se suscribe al Observer pero luego es destruida por el sistema operativo Android en condiciones de poca memoria (puede imitar este efecto activando las Opciones del desarrollador / No mantener actividades). Si el trabajo en Schedulers.io()
todavía se está ejecutando cuando la Actividad se destruye, se mantendrá una referencia a la Actividad a través de la clase interna anónima. Esto significa una pérdida de memoria que impide que la actividad sea finalizada por el recolector de basura. Si la Actividad tiene una cantidad de Vistas o, por ejemplo, un objeto Bitmap, la pérdida de memoria puede ser bastante importante.
Aquí hay una serie de soluciones, pero una de ellas es mantener un objeto onDestroy()
CompositeDisposable
y borrarlo en el método de ciclo de vida onDestroy()
de la Actividad de 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();
}
}
Puede consultar un buen ejemplo de cómo usar RxJava en una aplicación de Android en los planos oficiales de arquitectura de Google Android .