Ho avuto un problema strano in una delle mie attività. Quando torno da una foto o un video, nel mio onActivityResult
sto visualizzando una finestra di dialogo che consente all'utente di nominare la telecamera. Una volta che l'utente preme OK, invio onNext()
a un oggetto con il nome del file richiesto che copia il file (e mostra la finestra di avanzamento).Osservabili corse sul thread principale anche se subscribeOn() viene chiamato su un altro thread
Per qualche motivo la funzione map()
che fa la copia viene sempre chiamata sul thread principale, anche se chiamo 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);
}
});
}
Modifica della subscribeOn(Schedulers.io())
chiamata observeOn(Schedulers.io())
risolto il problema. Ancora mi piacerebbe sapere perché non ha funzionato ...
Questo è qualcosa di nuovo per me. Usando RxJava da un po 'di tempo, sono sicuro che il thread 'subscribeOn' si applica a tutti gli operatori downstream fino al primo' observOn' o ad un operatore con uno schedulatore specificato. Non è vero? In questo caso qual è la regola per la selezione del thread dopo 'subscribeOn'? – AndroidEx
Gli effetti di 'subscribeOn' vanno a monte e più vicini all'origine degli eventi. Pensalo come questo. hai una fonte ma vuoi iscriverti su una discussione diversa. Scriveresti 'new Thread (() -> source.subscribe (s)). Start();'. Qualcosa di simile accade in "subscribeOn". Hai scelto lo scheduler in base a ciò che accade quando ti iscrivi a quella fonte. Se apre immediatamente una connessione di rete o inizia a leggere un file lungo, vai per 'Schedulers.io()'. Se inizia a calcolare pesantemente qualcosa, fai 'computation()'. – akarnokd
Grazie. Anche se ero più interessato a ciò che succede dopo subscribeOn, a quale thread viene applicato il prossimo operatore. Dalle tue parole ho avuto l'impressione che non è garantito che sia il thread specificato in subscribeOn. – AndroidEx