java - sincronizacion - Observable se ejecuta en el hilo principal, aunque se llama a subscribeOn() en otro hilo
rxjava android (1)
subscribeOn
y observeOn
es la mayoría de los operadores confundidos que hay. El primero se asegura de que se produzcan efectos secundarios de suscripción en el programador especificado (subproceso), pero eso no significa que los valores también aparecerán en ese subproceso.
Por ejemplo, si su Observer abre una conexión de red cuando uno se suscribe a él, no desea que se ejecute en el hilo principal, por lo tanto, necesita suscribirse en On para especificar dónde se creará esa suscripción y, por lo tanto, la conexión de red.
Cuando los datos finalmente llegan, el subproceso que emite puede ser cualquier cosa, uno de los programadores o un subproceso de fondo simple. Como no sabemos o no nos gusta ese hilo, queremos mover la observación de los datos a otro hilo. Esto es lo que hace ObservOn: se asegura de que los operadores ejecutarán su lógica onNext en el programador especificado. Los desarrolladores de Android ya lo utilizan para mover la observación de valores al hilo principal.
Sin embargo, lo que rara vez se explica es lo que sucede cuando se desea un cálculo adicional fuera del hilo principal antes de que el resultado final observeOn
nuevamente al hilo principal: use varios operadores de observeOn
:
source
.observeOn(Schedulers.computation())
.map(v -> heavyCalculation(v))
.observeOn(Schedulers.io())
.doOnNext(v -> { saveToDB(v); })
.observeOn(AndroidSchedulers.mainThread())
...
Tengo un problema extraño en una de mis actividades. Cuando vuelvo de tomar una foto / video, en mi onActivityResult
estoy mostrando un diálogo que le permite al usuario nombrar la cámara. Una vez que el usuario presiona OK, envío onNext()
a un asunto con el nombre del archivo solicitado que copia el archivo (y muestra el cuadro de diálogo de progreso).
Por alguna razón, la función map()
que realiza la copia siempre se llama en el subproceso principal, a pesar de que llamo subscribeOn(Schedulers.io())
.
@Override
protected void onActivityResult(final int requestCode, int resultCode, Intent intent) {
...
final PublishSubject<String> subject = PublishSubject.create();`
mSubscription = subject
.subscribeOn(Schedulers.io())
.map(new Func1<String, String>() {
@Override
public String call(String fileName) {
Log.I.d(TAG,"map");
return doSomeIOHeavyFuncition();
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<String>() {
@Override
public void call(final String fullPath) {
Log.d(TAG,"onNext");
doSomethingOnUI(fullPath);
subject.onCompleted();
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
...
}
}, new Action0() {
@Override
public void call() {
...
}
});
final AlertDialog dialog = new AlertDialog.Builder
....
.create()
.show();
dialog.getButton(DialogInterface.BUTTON_POSITIVE)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String someString = getStringFromDialog(dialog);
dialog.dismiss();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(input.getWindowToken(), 0);
showProgressDialog();
subject.onNext(someString);
}
});
}
El cambio de la llamada subscribeOn(Schedulers.io())
a observeOn(Schedulers.io())
solucionó el problema. Todavía me gustaría saber por qué no funcionó ...