Je veux faire ça:
Observable.just(bitmap)
.map(new Func1<Bitmap, File>() {
@Override
public File call(Bitmap photoBitmap) {
//File creation throws IOException,
//I just want it to hit the onError() inside subscribe()
File photoFile = new File(App.getAppContext().getCacheDir(), "userprofilepic_temp.jpg");
if(photoFile.isFile()) {//delete the file first if it exists otherwise the new file won't be created
photoFile.delete();
}
photoFile.createNewFile(); //saves the file in the cache dir
FileOutputStream fos = new FileOutputStream(photoFile);
photoBitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);//jpeg format
fos.close();
return photoFile;
}
})
.subscribe(//continue implementation...);
Fondamentalement, dans la méthode call()
, il peut lever des exceptions. Comment puis-je faire en sorte que l'Observer le gère dans onError()
. Ou n'est-ce pas la bonne façon d'y penser?
rx détectera toujours une erreur, même s'il s'agit de RuntimeException. Vous pouvez donc lancer une sorte d'exception d'exécution dans le bloc catch. Voilà comment cela devrait fonctionner.
Observable.just(bitmap)
.map(b -> {
try {
// do some work which throws IOException
throw new IOException("something went wrong");
} catch (IOException e) {
throw new RXIOException(e);
// Or you can use
throw Exceptions.propagate(e);
// This helper method will wrap your exception with runtime one
}
}).subscribe(o -> {
// do something here
}, exception -> exception.printStackTrace());
public static class RXIOException extends RuntimeException {
public RXIOException(IOException throwable) {
super(throwable);
}
}
Avec 1.0.15, il existe la méthode d'usine fromCallable
qui vous permet d'exécuter une instance Callable
pour chaque abonné où vous pouvez également lever des exceptions vérifiées:
Observable.fromCallable(() -> {
File photoFile = new File(App.getAppContext().getCacheDir(),
"userprofilepic_temp.jpg");
if (photoFile.isFile()) {
//delete the file if it exists otherwise the new file won't be created
photoFile.delete();
}
photoFile.createNewFile(); //saves the file in the cache dir
FileOutputStream fos = new FileOutputStream(photoFile);
photoBitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);//jpeg format
fos.close();
return photoFile;
})
.subscribe(...)
Éditer:
source.flatMap(v -> {
try {
//...
return Observable.just(result);
} catch (Exception e) {
return Observable.error(e);
}
})
.subscribe(...);
Je viens de créer une classe d'assistance pour extraire ce passe-partout vers un autre endroit:
public class RxRethrow {
public static <T, R> Func1<T, R> rethrow(Func1R<T, R> catchedFunc) {
return t -> {
try {
return catchedFunc.call(t);
} catch (Exception e) {
throw Exceptions.propagate(e);
}
};
}
public interface Func1R<T, R> extends Function {
R call(T t) throws Exception;
}
}
Vous pouvez l'appeler comme ceci:
.map(RxRethrow.rethrow(products -> mapper.writer(schema).writeValueAsString(products)))
Je ne sais pas comment était la situation lorsque cette question a été posée et répondue pour la première fois, mais RxJava contient actuellement une méthode d'assistance dans ce but précis: Exceptions.propagate(Throwable t)
Méthode pratique pour lever directement une RuntimeException et une erreur ou envelopper tout autre type d'exception dans une RuntimeException.