使用OKHttp处理Volley的底层HTTP请求
原文:http://willyan.me/2013/06/01/volley-okhttp/
- 导入Volley(目前没有官方的jar包,需要自己下载源码编译);
git clone https://android.googlesource.com/platform/frameworks/volley
-
创建OkHttpStack
/**
* An {@link com.android.volley.toolbox.HttpStack HttpStack} implementation which
* uses OkHttp as its transport.
*/
public class OkHttpStack extends HurlStack {
private final OkHttpClient client;
public OkHttpStack() {
this(new OkHttpClient());
}
public OkHttpStack(OkHttpClient client) {
if (client == null) {
throw new NullPointerException("Client must not be null.");
}
this.client = client;
}
@Override protected HttpURLConnection createConnection(URL url) throws IOException {
return client.open(url);
}
}
- 创建Volley队列
Volley.newRequestQueue(context, new OkHttpStack());
参考链接:OkHttp作者Jake Wharton的Gist
修正:
貌似前面OkHttpStack已经不支持OkHttp2.0,见How to implement Android Volley with OkHttp 2.0? 。
现在的解决办法是:
下载或者设置对okhttp-urlconnection的依赖。
使用OkUrlFactory类重写OkHttpStack :
public class OkHttpStack extends HurlStack {
private final OkUrlFactory okUrlFactory;
public OkHttpStack() {
this(new OkUrlFactory(new OkHttpClient()));
}
public OkHttpStack(OkUrlFactory okUrlFactory) {
if (okUrlFactory == null) {
throw new NullPointerException("Client must not be null.");
}
this.okUrlFactory = okUrlFactory;
}
@Override
protected HttpURLConnection createConnection(URL url) throws IOException {
return okUrlFactory.open(url);
}}
另外
这篇文章也给出了一个OkHttpStack:
package com.sottocorp.sotti.okhttpvolleygsonsample.others;
import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.toolbox.HttpStack;
import com.squareup.okhttp.Call;
import com.squareup.okhttp.Headers;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Protocol;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;
import com.squareup.okhttp.ResponseBody;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.ProtocolVersion;
import org.apache.http.StatusLine;
import org.apache.http.entity.BasicHttpEntity;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicHttpResponse;
import org.apache.http.message.BasicStatusLine;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* OkHttp backed {@link com.android.volley.toolbox.HttpStack HttpStack} that does not
* use okhttp-urlconnection
*/
public class OkHttpStack implements HttpStack
{
private final OkHttpClient mClient;
public OkHttpStack(OkHttpClient client)
{
this.mClient = client;
}
@Override
public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)
throws IOException, AuthFailureError
{
OkHttpClient client = mClient.clone();
int timeoutMs = request.getTimeoutMs();
client.setConnectTimeout(timeoutMs, TimeUnit.MILLISECONDS);
client.setReadTimeout(timeoutMs, TimeUnit.MILLISECONDS);
client.setWriteTimeout(timeoutMs, TimeUnit.MILLISECONDS);
com.squareup.okhttp.Request.Builder okHttpRequestBuilder =
new com.squareup.okhttp.Request.Builder();
okHttpRequestBuilder.url(request.getUrl());
Map<String, String> headers = request.getHeaders();
for (final String name : headers.keySet())
{
okHttpRequestBuilder.addHeader(name, headers.get(name));
}
for (final String name : additionalHeaders.keySet())
{
okHttpRequestBuilder.addHeader(name, additionalHeaders.get(name));
}
setConnectionParametersForRequest(okHttpRequestBuilder, request);
com.squareup.okhttp.Request okHttpRequest = okHttpRequestBuilder.build();
Call okHttpCall = client.newCall(okHttpRequest);
Response okHttpResponse = okHttpCall.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
(com.squareup.okhttp.Request.Builder builder, Request<?> request)
throws IOException, AuthFailureError
{
switch (request.getMethod())
{
case Request.Method.DEPRECATED_GET_OR_POST:
// Ensure backwards compatibility.
// Volley assumes a request with a null body is a GET.
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);
}
}