How do I handle exceptions in map() in an Observable in RxJava
Solution 1
rx will always catch error, even if this is RuntimeException. So you can throw Some kind of Runtime exception in catch block. This is how actually it should work.
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);
}
}
Solution 2
With 1.0.15, there is the fromCallable
factory method which let's you run a Callable
instance for each subscriber where you can throw checked exceptions as well:
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(...)
Edit:
source.flatMap(v -> {
try {
//...
return Observable.just(result);
} catch (Exception e) {
return Observable.error(e);
}
})
.subscribe(...);
Solution 3
Just created helper class to extract this boilerplate to another place:
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;
}
}
You can call it like this:
.map(RxRethrow.rethrow(products -> mapper.writer(schema).writeValueAsString(products)))
Solution 4
I don't know how the situation was when this question was first asked and answered, but RxJava currently contains a helper-method for this exact purpose:
Exceptions.propagate(Throwable t)
Convenience method to throw a RuntimeException and Error directly or wrap any other exception type into a RuntimeException.
Sree
Updated on July 05, 2022Comments
-
Sree almost 2 years
I want to do this:
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...);
Basically in the
call()
method, it can throw exceptions. How can I make the Observer handle it inonError()
. Or is this not the right way to think about this?