使用OKHttp处理Volley的底层HTTP请求

jopen 9年前

原文:http://willyan.me/2013/06/01/volley-okhttp/ 

1) 导入Volley(目前没有官方的jar包,需要自己下载源码编译);

git clone https://android.googlesource.com/platform/frameworks/volley

2) 导入OkHttpokhttp-urlconnection

3) 创建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);    }     }

4) 创建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);      }  }