简体   繁体   English

抛出Observable.from()时未捕获RuntimeException

[英]RuntimeException not caught when thrown in Observable.from()

In order to update the progress when downloading a file,I customized a InputStreamToFileIterable class to work with rxjava: 为了更新下载文件时的进度,我自定义了InputStreamToFileIterable类以与rxjava一起使用:

public class InputStreamToFileIterable implements Iterable<Integer> {
    private InputStream inputStream;
    private FileOutputStream outputStream;
    private byte[] buffer;


    public InputStreamToFileIterable(InputStream inputStream, FileOutputStream outputStream) {
        this.inputStream = inputStream;
        this.outputStream = outputStream;
        this.buffer = new byte[512];
    }

    public Iterator<Integer> iterator() {
        return new InputStreamIterator();
    }

    class InputStreamIterator implements Iterator<Integer> {
        int data;
        boolean isClosed;
        int read;

        public InputStreamIterator() {
            read = 0;
            try {
                data = inputStream.read(buffer);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            isClosed = false;
        }

        @Override
        public boolean hasNext() {
            return data != -1;
        }

        @Override
        public Integer next() {
            read += data;
            try {
                if (isClosed){
                    throw new NoSuchElementException();
                }
                if (!hasNext()) {
                    inputStream.close();
                    outputStream.close();
                    isClosed = true;
                } else {
                    outputStream.write(buffer, 0, data);
                    data = inputStream.read(buffer);
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            return read;
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }

    }
}

However when I subscribe an Observable like this: 但是,当我订阅这样的Observable时:

subscriptionList.add(Observable.just(cachePath)
            .concatMap(new Func1<String, Observable<Integer>>() {
                @Override
                public Observable<Integer> call(String s) {
                    try {
                        isDownloading = true;
                        HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
                        connection.connect();
                        if (!file.getParentFile().exists()) {
                            file.getParentFile().mkdirs();
                        }
                        file.createNewFile();
                        fileOutputStream = new FileOutputStream(cachePath);
                        inputStream = connection.getInputStream();
                        total = connection.getContentLength();
                        return Observable.from(new InputStreamToFileIterable(inputStream, fileOutputStream));
                    } catch (Exception e) {
                        Log.d(TAG, e.getMessage());
                    }
                    return Observable.just(null);
                }
            })
            .filter(new Func1<Integer, Boolean>() {
                @Override
                public Boolean call(Integer integer) {
                    return integer!=null;
                }
            })
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(getObserverDownloadPicture()));

my observer can't catch the RuntimeException thrown by InputStreamIterator.next() if the inputStream is closed halfway.I will get a exception like this: 如果inputStream中途关闭,我的观察者将无法捕获InputStreamIterator.next()抛出的RuntimeException。我将得到如下异常:

04-16 22:39:18.393 16996-17031/me.wuke.weibo E/AndroidRuntime: FATAL EXCEPTION: RxCachedThreadScheduler-2
                                                           Process: me.wuke.weibo, PID: 16996
                                                           Theme: themes:{default=overlay:system, iconPack:system, com.android.systemui=overlay:system, com.android.systemui.navbar=overlay:system}
                                                           java.lang.IllegalStateException: Fatal Exception thrown on Scheduler.Worker thread.
                                                               at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:62)
                                                               at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423)
                                                               at java.util.concurrent.FutureTask.run(FutureTask.java:237)
                                                               at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:269)
                                                               at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
                                                               at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
                                                               at java.lang.Thread.run(Thread.java:818)
                                                            Caused by: java.lang.RuntimeException: java.net.SocketException: recvfrom failed: ETIMEDOUT (Connection timed out)
                                                               at me.wuke.weibo.utility.InputStreamToFileIterable$InputStreamIterator.next(InputStreamToFileIterable.java:60)
                                                               at me.wuke.weibo.utility.InputStreamToFileIterable$InputStreamIterator.next(InputStreamToFileIterable.java:27)
                                                               at rx.internal.operators.OnSubscribeFromIterable$IterableProducer.slowpath(OnSubscribeFromIterable.java:97)
                                                               at rx.internal.operators.OnSubscribeFromIterable$IterableProducer.request(OnSubscribeFromIterable.java:73)
                                                               at rx.internal.producers.ProducerArbiter.request(ProducerArbiter.java:66)
                                                               at rx.internal.operators.OperatorConcat$ConcatSubscriber.requestFromChild(OperatorConcat.java:124)
                                                               at rx.internal.operators.OperatorConcat$ConcatSubscriber.access$000(OperatorConcat.java:75)
                                                               at rx.internal.operators.OperatorConcat$ConcatProducer.request(OperatorConcat.java:70)
                                                               at rx.internal.operators.OperatorSubscribeOn$1$1$1$1.call(OperatorSubscribeOn.java:85)
                                                               at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
                                                               at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423) 
                                                               at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
                                                               at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:269) 
                                                               at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
                                                               at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
                                                               at java.lang.Thread.run(Thread.java:818) 
                                                            Caused by: java.net.SocketException: recvfrom failed: ETIMEDOUT (Connection timed out)
                                                               at libcore.io.IoBridge.maybeThrowAfterRecvfrom(IoBridge.java:588)
                                                               at libcore.io.IoBridge.recvfrom(IoBridge.java:552)
                                                               at java.net.PlainSocketImpl.read(PlainSocketImpl.java:481)
                                                               at java.net.PlainSocketImpl.-wrap0(PlainSocketImpl.java)
                                                               at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:237)
                                                               at com.android.okhttp.okio.Okio$2.read(Okio.java:135)
                                                               at com.android.okhttp.okio.AsyncTimeout$2.read(AsyncTimeout.java:211)
                                                               at com.android.okhttp.okio.RealBufferedSource.read(RealBufferedSource.java:50)
                                                               at com.android.okhttp.internal.http.HttpConnection$FixedLengthSource.read(HttpConnection.java:418)
                                                               at com.android.okhttp.okio.RealBufferedSource.read(RealBufferedSource.java:50)
                                                               at com.android.okhttp.internal.http.HttpEngine$2.read(HttpEngine.java:942)
                                                               at com.android.okhttp.okio.RealBufferedSource$1.read(RealBufferedSource.java:349)
                                                               at java.io.InputStream.read(InputStream.java:162)
                                                               at me.wuke.weibo.utility.InputStreamToFileIterable$InputStreamIterator.next(InputStreamToFileIterable.java:57)
                                                               at me.wuke.weibo.utility.InputStreamToFileIterable$InputStreamIterator.next(InputStreamToFileIterable.java:27) 
                                                               at rx.internal.operators.OnSubscribeFromIterable$IterableProducer.slowpath(OnSubscribeFromIterable.java:97) 
                                                               at rx.internal.operators.OnSubscribeFromIterable$IterableProducer.request(OnSubscribeFromIterable.java:73) 
                                                               at rx.internal.producers.ProducerArbiter.request(ProducerArbiter.java:66) 
                                                               at rx.internal.operators.OperatorConcat$ConcatSubscriber.requestFromChild(OperatorConcat.java:124) 
                                                               at rx.internal.operators.OperatorConcat$ConcatSubscriber.access$000(OperatorConcat.java:75) 
                                                               at rx.internal.operators.OperatorConcat$ConcatProducer.request(OperatorConcat.java:70) 
                                                               at rx.internal.operators.OperatorSubscribeOn$1$1$1$1.call(OperatorSubscribeOn.java:85) 
                                                               at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55) 
                                                               at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423) 
                                                               at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
                                                               at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:269) 
                                                               at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
                                                               at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
                                                               at java.lang.Thread.run(Thread.java:818) 
                                                            Caused by: android.system.ErrnoException: recvfrom failed: ETIMEDOUT (Connection timed out)
                                                               at libcore.io.Posix.recvfromBytes(Native Method)
                                                               at libcore.io.Posix.recvfrom(Posix.java:189)
                                                               at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:250)
                                                               at libcore.io.IoBridge.recvfrom(IoBridge.java:549)

I didn't forget to implement onError() method in my observer. 我没有忘记在观察者中实现onError()方法。

    public Observer getObserverDownloadPicture() {
    return Observers.create(
            new Action1<Integer>() {
                @Override
                public void call(Integer integer) {
                    onProgressChanged(integer * 100 / total);
                }
            }
            , new Action1<Throwable>() {
                @Override
                public void call(Throwable throwable) {
                    Log.e(TAG, throwable.getMessage());
                    try {
                        fileOutputStream.close();
                        isDownloading = false;
                        file.delete();
                    } catch (Exception e) {
                        ExceptionUtils.saveLog(e);
                    }
                    progressTextView.setText("载入失败");
                    subscriptionList.clear();
                }
            }
            , new Action0() {
                @Override
                public void call() {
                    try {
                        fileOutputStream.close();
                    } catch (Exception e) {
                        Log.d(TAG, e.getMessage());
                    }
                    if (isDownloading) {
                        setupPicture();
                    }
                    isDownloading = false;
                    subscriptionList.clear();
                }
            }
    );
}

How can I handle the Exception?Please help me with this. 我该如何处理异常?请帮助我。

Try to replace Exception in the catch block with a concrete exception. 尝试用具体异常替换catch块中的Exception Something like this: 像这样:

catch (IOException e) {
    Log.d(TAG, e.getMessage());
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如果抛出RuntimeException,它是否可以作为异常捕获? - If RuntimeException is thrown, can it be caught as an Exception? 在 arrayadapter 中交换数据时,从 binder 存根实现中捕获了 RuntimeException - Caught a RuntimeException from the binder stub implementation when swap data in arrayadapter Observable.from(需要在另一个线程上完成的事情) - Observable.from(something that needs to be done on another thread) RxJava2 Single已处置后,抛出RuntimeException且未将其捕获 - RuntimeException thrown and not caught in RxJava2 Single after it has been disposed 未抛出异常时捕获异常 - Exception is caught when Exception is not thrown 捕获了绑定器存根实现中的RuntimeException - Caught a RuntimeException from the binder stub implementation Observable.map引发的错误未在订阅中捕获 - Observable.map thrown error not getting caught in subscribe 为什么抛出 400 时未捕获 HttpStatusCodeException? - Why HttpStatusCodeException is not caught when a 400 is thrown? 在Rx Java中应用Observable.from()运算符后,再次连接项目 - Concatenate items again after applying Observable.from() operator in Rx Java 抛出 RuntimeException 时,Java 期望返回值 - Java expects return value when RuntimeException is thrown
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM