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

in technology •  6 years ago 

前几天使用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就直接闪退了。

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  

This post has been upvoted for free by @millibot with 5%!
Get better upvotes by bidding on me.
More profits? 100% Payout! Delegate some SteemPower to @millibot: 1 SP, 5 SP, 10 SP, custom amount
You like to bet and win 20x your bid? Have a look at @gtw and this description!