La enseñanza más fácil de entender para usar RxJava3
Terminología en Rxjava
1. Aguas arriba y aguas abajo
El flujo de datos en RxJava incluye una fuente de datos, 0 o más pasos intermedios, un consumidor de datos o subpasos combinados (los pasos son responsables de usar el flujo de datos de cierta manera):
source
.operator1()
.operator2()
.operator3()
.subscribe(consumer)
Desde la perspectiva del operador2, la fuente de la izquierda está aguas arriba y la suscripción (consumidor) de la derecha está aguas abajo.
2. El objeto del movimiento
En la documentación de RxJava, emisión, emisiones, elemento, evento, señal, datos y mensaje son sinónimos, y todos significan objetos que se mueven a lo largo del flujo de datos.
3. Contrapresión
El uso de contrapresión permite que el paso actual limite el uso de la memoria del flujo de datos cuando generalmente es imposible saber cuántos elementos de datos se enviarán en sentido ascendente.
En RxJava, las Flowable
clases están diseñadas para soportar la contrapresión y las Observable
clases están dedicadas a operaciones sin contrapresión. Single, Maybe y Completable tampoco soportan la contrapresión.
4. Programadores
Los operadores de RxJava no usan directamente Thread o ExecutorServices, pero usan el llamado Programador, que abstrae la fuente de concurrencia detrás de la API unificada.
Tipo de uso del programador
- Schedulers.computation (): Ejecuta trabajo computacionalmente intensivo en un número fijo de subprocesos dedicados en segundo plano. La mayoría de los operadores asincrónicos utilizan esto como su planificador predeterminado.
- Schedulers.io (): Ejecute operaciones de bloqueo o E / S similares en un grupo de subprocesos que cambian dinámicamente.
- Schedulers.single (): Ejecuta el trabajo en un solo hilo de forma secuencial y FIFO.
- Schedulers.trampoline (): Ejecuta trabajos de forma secuencial y FIFO en los hilos participantes, generalmente con fines de prueba.
Por supuesto, ciertas plataformas también tienen otro uso de programación , como el sistema Android tiene un uso adicional:
AndroidSchedulers.mainThread(), SwingScheduler.instance() or JavaFXSchedulers.gui().
También puede utilizar un servicio de programación de tareas ExecutorService [^ 1] personalizado a través del método Scheduler .from (Executor) . Tendrá un grupo de subprocesos más grande pero aún fijo (diferente de usar compute () e io () por separado).
Uso de observador y observable en Rxjava
El escenario de aplicación principal de la biblioteca de programación receptiva RxJava es asincrónico. Observer y Observable en
RxJava son dos clases o interfaces importantes. A continuación realizamos una prueba sencilla.
(1) Primero cree una instancia de Observable.
- Hay muchos métodos de creación, como create (), defer (), just (), from (), rang (), timer (), interval (), etc. Aquí se utiliza la creación más utilizada, y su parámetro es una instancia de ObservableOnSubscribe .
- ObservableOnSubscribe # subscribe ( emisor ObservableEmitter ) se volverá a llamar en este momento . El subscribe (emisor ObservableEmitter) hará una devolución de llamada de respuesta cuando el Observable esté suscrito, y su respuesta es después del método Observer # onSubscribe (Disposable d).
private ObservableEmitter<String> mEmitter;
private Observable<String> mObservable;
private void createObservable() {
mObservable = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) {
Log.i(TAG, " Observable has create");
mEmitter = emitter;
}
});
}
Llamar al método createObservable () subscribe (emisor ObservableEmitter) no responderá.
(2)
Para obtener una explicación detallada de los cuatro métodos de instanciar un objeto Observer Observer, consulte Observer
private Observer<String> mObserver = new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.i(TAG, " +++ onSubscribe");
if (d != null) {
System.out.println(" d.hashCode()=" + d.hashCode() + " mEmitter.hashCode() " + mEmitter.hashCode());
System.out.println(" d.getClass()=" + d.getClass().getCanonicalName());
}
}
@Override
public void onNext(String s) {
Log.i(TAG, " +++ onNext" + s);
}
@Override
public void onError(Throwable e) {
Log.i(TAG, " +++ onError");
}
@Override
public void onComplete() {
Log.i(TAG, " +++ onComplete");
}
};
(3) Observable se suscribe a
mObservable.subscribe (mObserver);
debe tenerse en cuenta que suscríbase para suscribirse (mObserver) varias veces, encontrará
public void onSubscribe(Disposable d) {
Log.i(TAG, " +++ onSubscribe");
if (d != null) {
System.out.println(" d.hashCode()=" + d.hashCode() + " mEmitter.hashCode() " + mEmitter.hashCode());
System.out.println(" d.getClass()=" + d.getClass().getCanonicalName());
}
}
- El método observer.onSubscribe se llama antes que Observable.subscribe
I: +++ onSubscribe
I: d.hashCode () = 464508421
I: d.getClass () = io.reactivex.internal.operators.observable.ObservableCreate.CreateEmitter
I: Observable has create
- d.getClass () = io.reactivex.internal.operators.observable.ObservableCreate.CreateEmitter sabe que d en onSubscribe (Disposable d) es una clase Emitter
- Al llamar a mObservable.subscribe (mObserver) varias veces, verifique el resultado de la impresión de la siguiente manera:
I / System.out: d.hashCode () = 464508421
I / System.out: mEmitter.hashCode () 464508421
I / System.out: d.hashCode () = 703714906
I / System.out: mEmitter.hashCode () 703714906
I / System.out: d.hashCode () = 786686091
I / System.out: mEmitter.hashCode () 786686091
Cada vez que se llama a mObservable.subscribe (mObserver), habrá una nueva subclase de implementación de Emitter y Disposable ( Disposable d y ObservableEmitter emitter hashCode son exactamente iguales ).
Explique que Observable.subscribe () creará un nuevo ObservableEmitter cada vez .
(4)
Después de que el observable cambia el estado del Observable, el ObservableEmitter transmite los datos a través de los métodos onNext, onComplete y onError, y el Observador suscrito responderá a los métodos onNext, onComplete y onError correspondientes. Como método de ejecución:
mEmitter.onNext("Hello");
mEmitter.onComplete();
La secuencia de respuesta del método es
ObservableEmitter.onNext
Observer.onNext
ObservableEmitter.onComplete
Observer.onComplete
y encontró que mEmitter.hashCode no cambiará
Si realiza varias mEmitter.onNext("Hello"); mEmitter.onComplete();
operaciones,
solo hay ObservableEmitter.onNext 、 ObservableEmitter.onComplete
dos formas de responder.
Observer.onNext 、 Observer.onComplete
No responderé. Esto está verificado. El observador solo responderá una vez al mismo cambio de estado.
Los enlaces relacionados son los siguientes: