如何在 RxJava 中的 Observable 中处理 map() 中的异常

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33556076/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 14:46:19  来源:igfitidea点击:

How do I handle exceptions in map() in an Observable in RxJava

javaandroidrx-javarx-android

提问by Sree

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 in onError(). Or is this not the right way to think about this?

基本上在call()方法中,它可以抛出异常。我怎样才能让观察者在onError(). 或者这不是思考这个问题的正确方式?

采纳答案by wnc_21

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.

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);
        }
}

回答by akarnokd

With 1.0.15, there is the fromCallablefactory method which let's you run a Callableinstance for each subscriber where you can throw checked exceptions as well:

在 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(...)

Edit:

编辑:

source.flatMap(v -> {
    try {
        //...
        return Observable.just(result);
    } catch (Exception e) {
        return Observable.error(e);
    }
})
.subscribe(...);

回答by MercurieVV

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)))

回答by Thorbear

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)

我不知道第一次提出和回答这个问题时的情况如何,但 RxJava 目前包含一个用于此确切目的的辅助方法: Exceptions.propagate(Throwable t)

RxJava Javadoc

RxJava Javadoc

Convenience method to throw a RuntimeException and Error directly or wrap any other exception type into a RuntimeException.

直接抛出 RuntimeException 和 Error 或将任何其他异常类型包装到 RuntimeException 的便捷方法。