Saltar al contenido

Rxandroid ¿Cuál es la diferencia entre SubscribeOn y ObserveOn?

Después de de nuestra extensa recopilación de información hemos podido solucionar esta impedimento que presentan ciertos usuarios. Te brindamos la respuesta y nuestro objetivo es servirte de gran apoyo.

Solución:

SubscribeOn especifica el Programador en el que operará un Observable. ObserveOn especifica el Programador en el que un observador observará este Observable.

Entonces, básicamente, SubscribeOn se suscribe (ejecuta) principalmente en un hilo de fondo (no desea bloquear el hilo de la interfaz de usuario mientras espera el observable) y también en ObserveOn desea observar el resultado en un hilo principal …

Si está familiarizado con AsyncTask, SubscribeOn es similar al método doInBackground y ObserveOn a onPostExecute …

En caso de que encuentre la respuesta anterior llena de jergas:

tl; dr

 Observable.just("Some string")                 
           .map(str -> str.length())              
           .observeOn(Schedulers.computation())   
           .map(length -> 2 * length)   
           .observeOn(AndroidSchedulers.mainThread())
           .subscribeOn(Schedulers.io())
           .subscribe(---)

Observar un observable, realizar la función de mapa en un IO hilo (ya que somos "subscribingOn" ese hilo), ahora cambia a un Hilo de computación y realizar map(length -> 2 * length) función ahora asegúrese de observar la salida en Principal hilo pero realizar todas las tareas definidas en subscribe() en un IO hilo.

De todos modos

observeOn() simplemente cambia el hilo de todos los operadores más Río abajo. La gente suele tener esto Idea equivocada ese observeOn también actúa como río arriba, pero no es así.

El siguiente ejemplo lo explicará mejor.

Observable.just("Some string")                  // UI
       .map(str -> str.length())               // UI
       .observeOn(Schedulers.computation())   // Changing the thread
       .map(length -> 2 * length)            // Computation
       .subscribe(---)

subscribeOn() solamente influencias el hilo que se utilizará cuando Observable se suscribirá y permanecerá en él en sentido descendente.

Observable.just("Some String")              // Computation
  .map(str -> str.length())                // Computation
  .map(length -> 2 * length)              // Computation
  .subscribeOn(Schedulers.computation()) // -- changing the thread
  .subscribe(number -> Log.d("", "Number " + number));// Computation

La posición no importa (subscribeOn())

¿Por qué? Porque afecta solo el momento de la suscripción.

Métodos que obedecen al contacto con subscribeOn

-> Ejemplo básico: Observable.create

Todo el trabajo especificado dentro del create el cuerpo se ejecutará en el hilo especificado en subscribeOn.

Otro ejemplo: Observable.just,Observable.from o Observable.range

Nota: Todos esos métodos aceptan valores, así que no use métodos de bloqueo para crear esos valores, ya que subscribeOn no lo afectará.

Si desea utilizar funciones de bloqueo, utilice

Observable.defer(() -> Obervable.just(blockingMenthod())));

Hecho importante:

subscribeOn no funciona con Subjects

Múltiple subscribeOn:

Si hay varias instancias de subscribeOn en la corriente, solo el primero uno tiene un efecto práctico.

Suscríbete y subscribeOn

La gente piensa que subscribeOn tiene algo que ver con Observable.subscribe, pero no tiene nada que ver con eso.
Solo afecta a la fase de suscripción.

Fuente: Tomek Polański (Medio)

Resumen

  • Usar observeOn establecer hilos para devoluciones de llamada “más abajo en la secuencia (debajo)”, como bloques de código dentro doOnNext o map.
  • Usar subscribeOn establecer hilos para inicializaciones “aguas arriba (arriba)”, como doOnSubscribe, Observable.just o Observable.create.
  • Ambos métodos se pueden llamar varias veces, y cada llamada sobrescribe las anteriores. La posición importa.

Repasemos este tema con un ejemplo: queremos encontrar la longitud de la string “usuario1032613”. Esta no es una tarea fácil para las computadoras, por lo que es natural que realicemos el cálculo intenso en un hilo en segundo plano, para evitar congelar la aplicación.

observar

Podemos llamar observeOn tantas veces como queramos, y controla qué hilo todos devoluciones de llamada debajo de él se ejecutará. Es fácil de usar y funciona tal como cabría esperar.

Por ejemplo, mostraremos una barra de progreso en el hilo principal de la IU, luego realizaremos operaciones intensivas / de bloqueo en otro hilo, luego regresaremos al hilo principal de la IU para actualizar el resultado:

    Observable.just("user1032613")

            .observeOn(mainThread) // set thread for operation 1
            .doOnNext 
                /* operation 1 */
                print("display progress bar")
                progressBar.visibility = View.VISIBLE
            

            .observeOn(backThread) // set thread for operation 2 and 3
            .map 
                /* operation 2 */
                print("calculating")
                Thread.sleep(5000)
                it.length
            

            .doOnNext 
                /* operation 3 */
                print("finished calculating")
            

            .observeOn(mainThread) // set thread for operation 4
            .doOnNext 
                /* operation 4 */
                print("hide progress bar and display result")
                progressBar.visibility = View.GONE
                resultTextView.text = "There're $it characters!"
            

            .subscribe()

En el ejemplo anterior, /* operation 1 */ se ejecuta en el mainThread porque lo configuramos usando observeOn(mainThread) en la línea justo encima de ella; luego cambiamos a backThread llamando observeOn de nuevo, entonces /* operation 2 */ correrá allí. Porque no lo cambiamos antes de encadenar /* operation 3 */, también se ejecutará en el hilo posterior, al igual que /* operation 2 */; finalmente llamamos observeOn(mainThread) de nuevo, para asegurarme /* operation 4 */ actualiza la interfaz de usuario desde el hilo principal.

subscribeOn

Así que hemos aprendido observeOn establece subprocesos para devoluciones de llamada posteriores. ¿Qué más nos estamos perdiendo? Bueno el Observable sí mismo, y sus métodos tales como just(), create(), subscribe() y así sucesivamente, también son códigos que deben ejecutarse. Así es como se pasan los objetos a lo largo de la corriente. Usamos subscribeOn para configurar subprocesos para el código relacionado con Observable sí mismo.

Si eliminamos todas las devoluciones de llamada (controladas por observeOn discutido anteriormente), nos queda el “código esqueleto” que, por defecto, se ejecutará en cualquier hilo en el que esté escrito el código (probablemente el hilo principal):

    Observable.just("user1032613")
            .observeOn(mainThread)
            .doOnNext 
            
            .observeOn(backThread)
            .map 
            
            .doOnNext 
            
            .observeOn(mainThread)
            .doOnNext 
            
            .subscribe()

Si no estamos contentos con este código esqueleto vacío que se ejecuta en el hilo principal, podemos usar subscribeOn para cambiarlo. Por ejemplo, tal vez la primera línea Observable.just("user1032613") no es tan simple como crear una transmisión a partir de mi nombre de usuario, tal vez sea una string de Internet, o tal vez esté utilizando doOnSubscribe para algunas otras operaciones intensivas. En ese caso, puede llamar subscribeOn(backThread) para poner parte del código en otro hilo.

Donde poner subscribeOn

En el momento de escribir esta respuesta, existen algunos conceptos erróneos que dicen “solo llámalo una vez”, “la posición no importa” y “si lo llamas varias veces, solo cuenta la primera vez”. Después de muchas investigaciones y experimentos, resulta subscribeOn se puede llamar de forma útil varias veces.

Porque Observable usa Builder Pattern (nombre elegante para “encadenar métodos uno tras otro”), subscribeOn se aplica en orden inverso. Por lo tanto, este método establece el hilo para código encima de él, exactamente lo contrario de observeOn.

Podemos experimentar esto usando doOnSubscribe método. Este método se activa en el evento de suscripción y se ejecuta en el subproceso establecido por subscribeOn:

    Observable.just("user1032613")
            .doOnSubscribe 
                print("#3 running on main thread")
            
            .subscribeOn(mainThread) // set thread for #3 and just()
            .doOnNext 
            
            .map 
            
            .doOnSubscribe 
                print("#2 running on back thread")
            
            .doOnNext 
            
            .subscribeOn(backThread) // set thread for #2 above
            .doOnNext 
            
            .doOnSubscribe 
                print("#1 running on default thread")
            
            .subscribe()

Podría ser más fácil seguir la lógica, si lee el ejemplo anterior de abajo a arriba, al igual que la forma en que Builder Pattern ejecuta el código.

En este ejemplo, la primera línea Observable.just("user1032613") se ejecuta en el mismo hilo que print("#3") porque no hay mas subscribeOn entre ellos. Esto crea la ilusión de que “solo importa la primera llamada” para las personas que solo se preocupan por el código interno just() o create(). Esto se desmorona rápidamente una vez que comienza a hacer más.


Nota:

Hilos y print() Las funciones en los ejemplos se definen, por brevedad, de la siguiente manera:

val mainThread = AndroidSchedulers.mainThread()
val backThread = Schedulers.computation()
private fun print(msg: String) = Log.i("", "$Thread.currentThread().name: $msg")

Sección de Reseñas y Valoraciones

Al final de todo puedes encontrar las notas de otros desarrolladores, tú asimismo tienes el poder mostrar el tuyo si lo deseas.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *