在RxJava中,如何在可观察对象中处理map()中的异常
我想这样做:在RxJava中,如何在可观察对象中处理map()中的异常,java,android,rx-java,rx-android,Java,Android,Rx Java,Rx Android,我想这样做: Observable.just(bitmap) .map(new Func1<Bitmap, File>() { @Override public File call(Bitmap photoBitmap) { //File creation throws IOException, //I just
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...);
Observable.just(位图)
.map(新函数1(){
@凌驾
公共文件调用(位图照片位图){
//文件创建引发IOException,
//我只想让它在subscribe()中点击onError()
File photoFile=新文件(App.getAppContext().getCacheDir(),“userprofilepic_temp.jpg”);
如果(photoFile.isFile()){//首先删除文件(如果存在),否则将不会创建新文件
photoFile.delete();
}
photoFile.createNewFile();//将文件保存在缓存目录中
FileOutputStream fos=新的FileOutputStream(照片文件);
photoBitmap.compress(Bitmap.CompressFormat.JPEG,90,fos);//JPEG格式
fos.close();
返回照片文件;
}
})
.subscribe(//继续实施…);
基本上在
call()
方法中,它可以抛出异常。如何让观察者在onError()
中处理它。或者这不是正确的思考方式吗?对于1.0.15,有一个fromCallable
工厂方法,让您为每个订阅者运行一个Callable
实例,您也可以在其中抛出选中的异常:
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(...)
编辑:
rx将始终捕获错误,即使这是RuntimeException。 所以您可以在catch块中抛出某种运行时异常。这就是它实际上应该如何工作
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);
}
}
刚刚创建了helper类以将此样板文件提取到另一个位置:
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;
}
}
我不知道这个问题第一次被问到和回答时的情况如何,但RxJava目前包含了一个用于此确切目的的helper方法:
异常。传播(可丢弃的t)
直接抛出RuntimeException和错误或将任何其他异常类型包装到RuntimeException中的方便方法
我想这在这种情况下是可行的,但是如果我想将依赖于第一个映射的输出的两个映射链接在一起呢。使用
Func1()
我可以获得返回类型和参数。您必须使用flatMap,尝试catch并返回just()或error()。工作起来像champ!!当我尝试这样做时,它要求我用一个try catch来包围异常,您必须抛出RuntimeException。JVM不会要求您用try-catch来包围它。这就是我的想法,让call()
抛出一个IOException,但它说重写的方法不会抛出IOExceptionName。IOException不是运行时异常。再读一遍我的答案。啊,对不起。完全有道理。你能看一下上面@akarnokd的答案吗?它使用了Observable.error
。您会推荐您的方法吗?请注意,在RXJava2中,像map
这样的操作符允许从lambda抛出已检查的异常。这实际上是RxJava 1中的一个设计缺陷,因为抛出的确切错误无法在映射lambda的“onError”中传播,而不会包装为RuntimeException
@Sree哇,我实际上没有发现这一点,我被自定义异常类蒙蔽了双眼。现在,我仔细看,我可以看到,实际上有另一个答案在这里使用相同的方法。
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;
}
}
.map(RxRethrow.rethrow(products -> mapper.writer(schema).writeValueAsString(products)))