Retrofit+Rxjava--xxException: The supplied value is null 错误分析

崩溃日志如下:

08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err: io.reactivex.exceptions.OnErrorNotImplementedException: The supplied value is null
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at io.reactivex.internal.functions.Functions$OnErrorMissingConsumer.accept(Functions.java:704)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at io.reactivex.internal.functions.Functions$OnErrorMissingConsumer.accept(Functions.java:701)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at io.reactivex.internal.observers.LambdaObserver.onError(LambdaObserver.java:74)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at io.reactivex.observers.SerializedObserver.onError(SerializedObserver.java:155)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at io.reactivex.internal.operators.observable.ObservableTakeUntil$TakeUntilObserver.onError(ObservableTakeUntil.java:73)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.checkTerminated(ObservableObserveOn.java:276)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.drainNormal(ObservableObserveOn.java:172)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.run(ObservableObserveOn.java:252)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run(HandlerScheduler.java:109)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at android.os.Handler.handleCallback(Handler.java:725)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:92)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at android.os.Looper.loop(Looper.java:137)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:5069)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at java.lang.reflect.Method.invokeNative(Native Method)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at java.lang.reflect.Method.invoke(Method.java:511)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at dalvik.system.NativeStart.main(Native Method)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err: Caused by: java.lang.NullPointerException: The supplied value is null
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at io.reactivex.internal.operators.observable.ObservableOnErrorReturn$OnErrorReturnObserver.onError(ObservableOnErrorReturn.java:81)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at retrofit2.adapter.rxjava2.BodyObservable$BodyObserver.onError(BodyObservable.java:72)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at retrofit2.adapter.rxjava2.CallExecuteObservable.subscribeActual(CallExecuteObservable.java:55)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at io.reactivex.Observable.subscribe(Observable.java:10842)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at retrofit2.adapter.rxjava2.BodyObservable.subscribeActual(BodyObservable.java:34)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at io.reactivex.Observable.subscribe(Observable.java:10842)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at io.reactivex.internal.operators.observable.ObservableOnErrorReturn.subscribeActual(ObservableOnErrorReturn.java:31)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at io.reactivex.Observable.subscribe(Observable.java:10842)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:452)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:61)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:52)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:234)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:153)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:267)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at java.lang.Thread.run(Thread.java:856)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err: Caused by: java.lang.IllegalStateException: closed
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at okio.RealBufferedSource.read(RealBufferedSource.java:43)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at okio.ForwardingSource.read(ForwardingSource.java:35)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at retrofit2.OkHttpCall$ExceptionCatchingRequestBody$1.read(OkHttpCall.java:291)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at okio.RealBufferedSource.request(RealBufferedSource.java:67)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at okio.RealBufferedSource.rangeEquals(RealBufferedSource.java:408)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at okio.RealBufferedSource.rangeEquals(RealBufferedSource.java:392)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at okhttp3.internal.Util.bomAwareCharset(Util.java:431)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at okhttp3.ResponseBody$BomAwareReader.read(ResponseBody.java:249)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at com.google.gson.stream.JsonReader.fillBuffer(JsonReader.java:1287)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at com.google.gson.stream.JsonReader.nextNonWhitespace(JsonReader.java:1325)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at com.google.gson.stream.JsonReader.doPeek(JsonReader.java:549)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at com.google.gson.stream.JsonReader.peek(JsonReader.java:425)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:205)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:37)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:25)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at retrofit2.ServiceMethod.toResponse(ServiceMethod.java:119)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:218)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at retrofit2.OkHttpCall.execute(OkHttpCall.java:180)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:     at retrofit2.adapter.rxjava2.CallExecuteObservable.subscribeActual(CallExecuteObservable.java:41)
08-15 13:46:34.277 2007-2007/com.ppdai.huanapp W/System.err:    ... 15 more

仔细查看以上日志,发现发生空指针异常的地方并不是在自己代码中,这也加大了修复难度,只能逐步查看调用堆栈,找出具体问题点,接下来和我一起来分析这个问题吧, Let's go!!

步骤一:Caused by: java.lang.NullPointerException: The supplied value is null

根据Caused by: java.lang.NullPointerException: The supplied value is null,打开ObservableOnErrorReturn.java文件,代码如下:

public void onError(Throwable t) {
            T v;
            try {
                v = valueSupplier.apply(t);
            } catch (Throwable e) {
                Exceptions.throwIfFatal(e);
                actual.onError(new CompositeException(t, e));
                return;
            }

            if (v == null) {
                NullPointerException e = new NullPointerException("The supplied value is null");
                e.initCause(t);
                actual.onError(e);
                return;
            }

            actual.onNext(v);
            actual.onComplete();
        }

到这里我们知道这个空指针异常时手动抛出来的,同时发现这个异常是因为v == null, 也就是网络请求结果为空。我们再往下看

步骤二: Caused by: java.lang.IllegalStateException: closed

根据 Caused by: java.lang.IllegalStateException: closed,打开(RealBufferedSource.java:43)文件,代码如下:

@Override public long read(Buffer sink, long byteCount) throws IOException {
    if (sink == null) throw new IllegalArgumentException("sink == null");
    if (byteCount < 0) throw new IllegalArgumentException("byteCount < 0: " + byteCount);
    if (closed) throw new IllegalStateException("closed");

    if (buffer.size == 0) {
      long read = source.read(buffer, Segment.SIZE);
      if (read == -1) return -1;
    }

    long toRead = Math.min(byteCount, buffer.size);
    return buffer.read(sink, toRead);
  }

同样这个一场也是手动抛出来,抛异常的条件是closed为真,接下来我们查看该bool值在哪可以修改,通过搜索该值,发现以下方法:

 @Override public void close() throws IOException {
    if (closed) return;
    closed = true;
    source.close();
    buffer.clear();
  }

至此我们明白了[The supplied value is null]的最终原因,原因找到了,接下来我们再来找解决方案

步骤三:close方法断点,查看调用堆栈。

调用堆栈如下:


Retrofit+Rxjava--xxException: The supplied value is null 错误分析_第1张图片

终于看到了自己的代码(开心中......),打开对应的文件,代码如下:

.addInterceptor(new Interceptor() {
                    @Override
                    public Response intercept(Chain chain) throws IOException {
                        Response response = chain.proceed(chain.request());
                        

                        MediaType mediaType = response.body().contentType();

                        LogUtils.e(chain.request().url().toString());
                        LogUtils.e(chain.request().body());
                        String content = response.body().string();
                        LogUtils.e(content);

                        return response;
                    }
                })

这个拦截器是为了打印网络请求日志,调用了response.body().string()方法,而string()方法有调用了Util.closeQuietly(source)方法,代码如下:

public final String string() throws IOException {
    BufferedSource source = source();
    try {
      Charset charset = Util.bomAwareCharset(source, charset());
      return source.readString(charset);
    } finally {
      Util.closeQuietly(source);
    }
  }

步骤四:解决问题

方案1:直接删除 response.body().string()的调用,这里你可能会说,我就想打印入职,要怎么办?
方案2:调用万 response.body().string()方法,我们创建一个新的 response返回,代码如下:

 .addInterceptor(new Interceptor() {
                    @Override
                    public Response intercept(Chain chain) throws IOException {
                         .......
                        MediaType mediaType = response.body().contentType();
                        ......
                   
                        String content = response.body().string();
                        LogUtils.e(content);
                        return response.newBuilder()
                                .body(ResponseBody.create(mediaType, content))
                                .build();
                    }
                })

总结:

遇到问题不能急,要根据已有的信息,逐步找到问题所在,找到了问题所在,就离解决问题不远了!!!

更多内容可以关注我的公众号或者搜索SamuelAndroid关注我:

Retrofit+Rxjava--xxException: The supplied value is null 错误分析_第2张图片
公众号

你可能感兴趣的:(Retrofit+Rxjava--xxException: The supplied value is null 错误分析)