前言
打一来这公司,就使用的是volley框架进行网络请求。众所周知,目前最火的就是retrofit+okhttp+rxjava,只因一直在开发新功能,没有排开时间来替换,所以就将就着用了。可问题来了,最近老大总是抱怨android的网络请求慢,而且总是会超时,体验了一下公司ios客户端,网络请求确实快,也不会出现超时这种现象。怎么办呢?看下SD卡的网络错误日志,
com.android.volley.VolleyError.TimeoutError
看到这里,马上我们就会觉得偶尔出现这个是正常的,网络问题嘛,随时可能抽风。最多就是把网络连接超时时间设置长点。我们知道,volley默认的网络超时时间是2.5秒。所以,这对于弱网络环境下是不够的。于是,我把时间设置为了10s,如下
//操作超时时间 public static final int CUD_SOCKET_TIMEOUT = 10000; //最大重试请求次数 public static final int MAX_RETRIES = 0; request.setRetryPolicy(new DefaultRetryPolicy(CUD_SOCKET_TIMEOUT, MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));这里通过setRetryPolicy方法来设置,传入RetryPolicy参数,这里我们创建它的继承类DefaultRetryPolicy就好,超时时间设置为10s,重试次数为0,最好设置为0。如果设置为>0的次数,volley好像有个BUG,在弱网络情况下会进行两次请求。
改好之后,这就完事了吗?NO,还是会间隔性的出现TimeOut,怎么办,再加长时间?我们也要考虑下用户体验,在10s内请求到还算好,超过10s用户体验就不好了。既然还是不行,那就用okhttp请求吧,要知道,volley使用的是HttpUrlConnect和HttpClient进行请求的。请求速度在网络框架里面并不是最好的,它适用轻量级数据高并发请求。那么为什么要换 okhttp呢,相对来说,okhttp请求速度还是比HttpUrlConnect更快的,因为oKHttp使用的请求类似于增强版的HTTPURLConnect。它的好处有如下几个:
1、支持HTTP1.1/HTTP1.2/SPDY协议,要知道谷歌浏览器现在也用SPDY协议了。
2,默认支持HTTPS请求,CA颁发的正式,自签名不行
3,HTTP请求的header体和body体GZip压缩
4,使用阻塞式线程池,优化网络请求队列
5、支持拦截器,调试方便
所以,干嘛不换呢。那么,我们又该怎么配置Volley,使Volley使用OKHTTP请求呢,通过查看代码,我们发现,我们可以传递自己的HttpStack,那么就好办了,我们创建一个HttpStack的子类就好了。
接下来在build.gradle文件里面导入okhttp3。
compile 'com.squareup.okhttp3:okhttp:3.5.0'
compile('com.squareup.okhttp3:logging-interceptor:3.5.0')
compile 'com.squareup.okio:okio:1.7.0'
然后,我们在创建RequestQueue单例里面配置下就好了。
public class OkHttpStack implements HttpStack { private OkHttpClient okHttpClient; public OkHttpStack() { okHttpClient = new OkHttpClient(); } @Override public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders) throws IOException, AuthFailureError { int timeOutMs = request.getTimeoutMs(); /* HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() { @Override public void log(String message) { ZLogUtil.d("zgx", "OkHttp====headAndBody" + message); } }); //包含header、body数据 loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);*/ Dispatcher dispatcher = okHttpClient.dispatcher(); dispatcher.setMaxRequestsPerHost(15); OkHttpClient.Builder okHttpBuilder = new OkHttpClient().newBuilder(); OkHttpClient resultOkHttpClient = okHttpBuilder .connectTimeout(timeOutMs, TimeUnit.MILLISECONDS) .readTimeout(timeOutMs,TimeUnit.MILLISECONDS) .writeTimeout(timeOutMs,TimeUnit.MILLISECONDS) .dispatcher(dispatcher) //.addInterceptor(loggingInterceptor) .build(); Map<String, String> headerMaps = request.getHeaders(); Headers headers = Headers.of(headerMaps); okhttp3.Request.Builder okHttpReqBuilder = new okhttp3.Request .Builder() .url(request.getUrl()) .headers(headers); setConnectionParametersForRequest(okHttpReqBuilder, request); Response okHttpResponse = resultOkHttpClient .newCall(okHttpReqBuilder.build()) .execute(); StatusLine responseStatus = new BasicStatusLine ( parseProtocol(okHttpResponse.protocol()), okHttpResponse.code(), okHttpResponse.message() ); BasicHttpResponse response = new BasicHttpResponse(responseStatus); response.setEntity(entityFromOkHttpResponse(okHttpResponse)); Headers responseHeaders = okHttpResponse.headers(); for (int i = 0, len = responseHeaders.size(); i < len; i++) { final String name = responseHeaders.name(i), value = responseHeaders.value(i); if (name != null) { response.addHeader(new BasicHeader(name, value)); } } return response; } private static HttpEntity entityFromOkHttpResponse(Response r) throws IOException { BasicHttpEntity entity = new BasicHttpEntity(); ResponseBody body = r.body(); entity.setContent(body.byteStream()); entity.setContentLength(body.contentLength()); entity.setContentEncoding(r.header("Content-Encoding")); if (body.contentType() != null) { entity.setContentType(body.contentType().type()); } return entity; } @SuppressWarnings("deprecation") private static void setConnectionParametersForRequest (okhttp3.Request.Builder builder, Request<?> request) throws IOException, AuthFailureError { switch (request.getMethod()) { case Request.Method.DEPRECATED_GET_OR_POST: byte[] postBody = request.getPostBody(); if (postBody != null) { builder.post(RequestBody.create (MediaType.parse(request.getPostBodyContentType()), postBody)); } break; case Request.Method.GET: builder.get(); break; case Request.Method.DELETE: builder.delete(); break; case Request.Method.POST: builder.post(createRequestBody(request)); break; case Request.Method.PUT: builder.put(createRequestBody(request)); break; case Request.Method.HEAD: builder.head(); break; case Request.Method.OPTIONS: builder.method("OPTIONS", null); break; case Request.Method.TRACE: builder.method("TRACE", null); break; case Request.Method.PATCH: builder.patch(createRequestBody(request)); break; default: throw new IllegalStateException("Unknown method type."); } } private static ProtocolVersion parseProtocol(final Protocol p) { switch (p) { case HTTP_1_0: return new ProtocolVersion("HTTP", 1, 0); case HTTP_1_1: return new ProtocolVersion("HTTP", 1, 1); case SPDY_3: return new ProtocolVersion("SPDY", 3, 1); case HTTP_2: return new ProtocolVersion("HTTP", 2, 0); } throw new IllegalAccessError("Unkwown protocol"); } private static RequestBody createRequestBody(Request r) throws AuthFailureError { final byte[] body = r.getBody(); if (body == null) return null; return RequestBody.create(MediaType.parse(r.getBodyContentType()), body); } }
这样,就配置好了Volley使用OkHttp请求了。接下来奇葩的事就出来了。
publicvoidinitialize(Context context) { if(mRequestQueue==null) mRequestQueue = Volley.newRequestQueue(context,new OkHttpStack()); mRequestQueue.start(); }
1,在公司wifi,android访问云端还是会出现间隔性的TimeoutError问题,而且是毫无规律的,ios访问就不会有这个现象
2、在家用wifi,访问就确实是比以前快多了。
3、使用手机数据连接3G或者4G访问也快。
这里记录下自己尝试的方法
1、优化网络请求频率,要知道,没有配置okhttp的情况下,volley在弱网的情况下,网络延时还是挺大的,优化的并不够好。
2,使用fidder手机抓包,抓包的时候不会出现这个问题。
3,ping云端ip,看是否会出现timeOutError问题,可以使用oneAPM或者jmeter压力测试。
4,猜想公司使用的是二级域名,后来发现公司使用wifi和家用wifi没有什么区别的,都是AP+路由。
5、是否和HTTPS和HTTPDNS有关,后来发现也没有关系。
6、通过Dispatcher加大okhttp每秒的最大请求数。
经过多种方式尝试,结果并没有解决公司wifi情况下这种间隔性超时的问题。最后,经过各种google搜索,终于找到一篇博客,和这种情况一模一样的,阿里云ECS上APP访问异常或超时
原因: 导致请求阿里云ECS上的APP访问超时或访问慢,是由于移动端发送过来的TCP包的时间戳是乱的,所以服务器将这些包给丢弃了。 解决方案: #vim /etc/sysctl.config net.ipv4.tcp_tw_recycle = 0 // net.ipv4.tcp_tw_recycle 设置为1,则开启!设置为0为关闭!记录时间戳 #sysctl -p
相关推荐
Volley和OkHttp是两种广泛使用的网络请求库,在Android应用开发中扮演着重要角色。Volley是由Google开发的网络通信库,它强调了快速响应和轻量级的特性,适合处理大量的小数据请求,如获取JSON数据或者图片加载。而...
- 将OkHttp的OkHttpClient实例配置给Volley的HttpStack,这样Volley就会利用OkHttp进行网络通信。 4. 关于提供的文件: - okhttp-urlconnection-2.2.0.jar:这是OkHttp的URLConnection适配器,用于在使用 ...
本篇文章将详细讲解Volley、OkHttp和Retrofit这三种常用的网络请求库的基本用法,帮助开发者更好地理解和选择适合自己的请求方式。 **Volley** Volley是由Google官方推出的网络请求库,它专注于Android平台,提供...
Volley用OkHttp3作为底部的框架的一个解决方案。Android6.0删除了一些org.apache.http包中的一些类,所以网上的一些解决方案就会有一点不太合适。下面是我自己写了一个解决方案。
本篇文章将详细探讨三个流行的网络库:Volley、OkHttp和Retrofit,它们各自的特点、用法以及如何进行GET和POST请求。 首先,Volley是由Google推出的网络请求库,其设计目标是提供一个高效、易用的网络请求框架。...
A http request engine based on Volley and OkHttp, giving up Apache HttpClient request. supports image loading, restful api requesting, and file downloading. READ MORE Dependency binary on jcenter ...
Volley-OkHttp-Android 该库是一个Android网络抽象库,由Volley,OkHttp和Jackson组合而成,并带有一些胶水将它们粘在一起。 如果您需要执行请求,尤其是返回JSON的请求,那么这是一个很好的起点。
为了简化这一过程,开发者通常会使用第三方网络框架,例如Volley、xUtils和OkHttp。这些框架提供了高效、易用的API,帮助开发者快速实现网络数据的获取和传输。接下来,我们将详细讨论这三个著名的网络库。 1. **...
《煎蛋项目OkHttp与Volley的深度解析》 在Android开发中,网络请求是必不可少的一部分,本项目“煎蛋项目okhttp_volley”正是基于OkHttp和Volley这两个强大的网络库来构建的。本文将深入探讨这两个组件的原理、优势...
本篇文章将深入探讨如何利用Volley、XUtils和OkHttp这三种流行的网络库来实现单张或多张图片的上传。下面我们将逐一介绍每种方法的关键步骤和注意事项。 ### Volley 图片上传 Volley是Google推出的网络请求库,以...
RxVolley是一个基于Volley的网络请求库;同时支持RxJava;可以选择使用OKHttp替代默认的 HttpUrlConnection 做网络请求;可以选择使用图片加载功能(复用的网络请求将有效减少apk体积);移除了原Volley的 HttpClient ...
> RxVolley = Volley RxJava OkHttp 中文帮助 Retrofit? No, I like Volley. RxVolley is modified Volley. Removed the HttpClient, and support RxJava. If you are building with Gradle, simply add the ...
OkHttp 适用于Android和Java应用程序的HTTP&SPDY客户端。 HTTP / 2和SPDY支持允许对同一主机的所有请求共享一个套接字。 连接池可减少请求延迟(如果SPDY不可用)。 透明的GZIP缩小了下载大小。 响应缓存可以...
相比其他网络库,如HttpURLConnection或Volley,OkHttp提供了以下几点优势: 1. **连接池**:OkHttp可以复用先前建立的TCP连接,减少网络延迟,提高响应速度。 2. **缓存机制**:OkHttp内置了缓存机制,可以自动...
通过阅读和理解这些代码,开发者可以更好地理解和应用这种网络请求解决方案,同时也能灵活地根据项目需求调整OkHttp和Volley的配置。 总的来说,Android的Volley和OkHttp的结合使用,为开发者提供了高效、安全且...
相较于其他网络库,如HttpURLConnection或Volley,OkHttp提供了更好的性能和更低的内存占用。 **1. OkHttp的初始化** 在使用OkHttp前,我们需要先创建一个OkHttpClient实例。这个实例可以配置各种参数,比如超时...
Android Networking I: OkHttp, Volley and Gson This is a sample app which demonstrates and shows what it's explained in a Medium article about networking in Android. Check out the next article for ...
3. 配置 VolleyRequestQueue:现在,我们需要在初始化 VolleyRequestQueue 时使用我们的自定义 HttpStack。以下是如何做到这一点的示例代码: ```java public class VolleyToolbox { public static void init...
Android Network DemoThis demo shows how to use volley with OkHttp and security your api with https.本文同步发于代码结构说明tools 文件夹下是相关的工具 dumps.sh 是一个导出证书并转换成 BKS 存储的完整脚本...