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 realizarmap(length -> 2 * length)
función ahora asegúrese de observar la salida en Principal hilo pero realizar todas las tareas definidas ensubscribe()
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 dentrodoOnNext
omap
. - Usar
subscribeOn
establecer hilos para inicializaciones “aguas arriba (arriba)”, comodoOnSubscribe
,Observable.just
oObservable.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.