This post is from a low-reputation account and contains an unverified outbound link. Be cautious before clicking external links.

Retrofit + okHttp使用中遇到的FATAL EXCEPTION: OkHttp Dispatcher问题

Words
411
Reading
2 min
Listen
Play
8y

前几天使用retrofit + okHttp 时出现一个问题,大致情况是使用okHttp上传视频文件时app闪退,错误如下:

 
FATAL EXCEPTION: OkHttp Dispatcher

Process: com.******.******.******, PID: 26206
java.lang.OutOfMemoryError: Failed to allocate a 144207294 byte allocation with 16765168 free bytes and 109MB until OOM
   at java.lang.StringFactory.newStringFromBytes(StringFactory.java:79)
   at java.lang.StringFactory.newStringFromBytes(StringFactory.java:207)
   at okio.Buffer.readString(Buffer.java:616)
   at okio.Buffer.readString(Buffer.java:599)
   at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:199)
   at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
   at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
   at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:170)
   at okhttp3.RealCall.access$100(RealCall.java:33)
   at okhttp3.RealCall$AsyncCall.execute(RealCall.java:120)
   at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)

        开始因为下面还有 OutOfMemoryError 的错,怀疑是视频有问题检查,视频文件正常大小有110M,虽然大点但不应该有问题,后来定位到自定义的okHttpClient配置的log拦截器处报错:

    
//新建log拦截器

        HttpLoggingInterceptor loggingInterceptor=new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
            @Override
            public void log(String message) {
                try {
                    L.w("屏幕修复api"," "+message); //报错处
                } catch (Exception e) {
                    e.printStackTrace();
                    L.w("屏幕修复api  Exception",e.toString());
                }

            }
        });

        try{}catch()是调试的时候加的,即使加上try{}catch()仍然报错,所以说HttpLoggingInterceptor内部的错,于是各种查资料,类似情况还真有比较普遍原因是:

String data=response.body().string();
//.string()方法使用次数超过了一次。没错,你只能使用一次,至于原因看下面的源码分析。

//所以讲Log.d(“xx”,response.body().string());果断的注释掉吧。

        感觉上面的错误只是方法调用有问题,不是真正的原因,继续查找,最后在Github okHttp的源码issues中找到这个cancel a async call will cause FATAL EXCEPTION #1049,源码作者之一在issues下说:We are seeing this issue too when we call cancel operation.当 call cancel operation 时会发生这个错误,至此问题算是清楚了。

总结:我的代码引起这个错的原因不值一提,是在上传文件时同时传有其他参数,那个参数不符合服务器要求,所以服务器不接收request(文件、参数1、参数2...),那么app这边就会 call cancel operation 引起了app闪退,算是okhttp的一个bug,作者最后也说了:I was hoping if we could either catch that exception properly, or find a way to neglect that issue ?所以这个bug不会被catch到,我们更拿不到这个错误,也就无法处理,app就直接闪退了。

Retrofit + okHttp使用中遇到的FATAL EXCEPTION: OkHttp Dispatcher问题 | Ecency