Как мне обработать исключения в map () в Observable в RxJava

Я хочу сделать это:

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

В основном в методе call(), он может генерировать исключения. Как я могу заставить Обозревателя справиться с этим в onError(). Или это не правильный способ думать об этом?

17
задан greatwolf 30 April 2017 в 06:27
поделиться

4 ответа

rx всегда будет ловить ошибку, даже если это RuntimeException. Таким образом, вы можете выбросить какое-то исключение Runtime в блоке 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);
        }
}
19
ответ дан Dave Moten 30 April 2017 в 06:27
поделиться

В версии 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(...)

Редактировать:

source.flatMap(v -> {
    try {
        //...
        return Observable.just(result);
    } catch (Exception e) {
        return Observable.error(e);
    }
})
.subscribe(...);
7
ответ дан falvojr 30 April 2017 в 06:27
поделиться

Только что созданный вспомогательный класс для извлечения этого шаблона в другое место:

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)))
3
ответ дан MercurieVV 30 April 2017 в 06:27
поделиться

Я не знаю, как была ситуация, когда этот вопрос был впервые задан и получен ответ, но RxJava в настоящее время содержит вспомогательный метод для этой конкретной цели: Exceptions.propagate(Throwable t)

RxJava Javadoc

Удобный метод для прямого выброса RuntimeException и Error или включения любого другого типа исключения в RuntimeException.

2
ответ дан Thorbear 30 April 2017 в 06:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: