Volley支援HTTP/2
阿新 • • 發佈:2018-12-07
volley暫時是不支援HTTP/2的,這是官方的解釋Does volley Support HTTP/2
不過volley設計的擴充套件性特別好,volley提供的介面HttpStack
,可以自己去實現來支援HTTP/2。在Android上,從4.4以後系統就已經支援HTTP/2,但是不穩定,有bug,直到Android5.0才修復bug。第三方庫中,有OkHttp
是已經支援了HTTP/2,所以我們可以使用OkHttp
來實現。
具體實現,可以參考OkHttp3Stack
自己的實現如下:
@SuppressWarnings("deprecation")
public class OkHttpStack implements HttpStack {
private final OkHttpClient mOkHttpClint;
public OkHttpStack(OkHttpClient okHttpClient) {
this.mOkHttpClint = okHttpClient;
}
public OkHttpStack() {
mOkHttpClint = new OkHttpClient();
}
@Override
public HttpResponse performRequest (Request<?> request, Map<String, String> additionalHeaders) throws IOException, AuthFailureError {
OkHttpClient.Builder builder = mOkHttpClint.newBuilder();
int timeoutMs = request.getTimeoutMs();
builder.connectTimeout(timeoutMs, TimeUnit.MILLISECONDS);
builder.readTimeout(timeoutMs, TimeUnit.MILLISECONDS);
builder.writeTimeout(timeoutMs, TimeUnit.MILLISECONDS);
okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder();
requestBuilder.url(request.getUrl());
Map<String, String> headers = request.getHeaders();
if (headers != null) {
for (String key : headers.keySet()) {
String value = headers.get(key);
if (TextUtils.isEmpty(value)) {
continue;
}
requestBuilder.addHeader(key, value);
}
}
if (additionalHeaders != null) {
for (String key : additionalHeaders.keySet()) {
String value = additionalHeaders.get(key);
if (TextUtils.isEmpty(value)) {
continue;
}
requestBuilder.addHeader(key, value);
}
}
setConnectionParametersForRequest(requestBuilder, request);
okhttp3.Request okRequest = requestBuilder.build();
OkHttpClient okClient = builder.build();
Call call = okClient.newCall(okRequest);
Response okResponse = call.execute();
BasicStatusLine statusLine = new BasicStatusLine(parseProtocol(okResponse.protocol()), okResponse.code(), okResponse.message());
BasicHttpResponse httpResponse = new BasicHttpResponse(statusLine);
httpResponse.setEntity(entityFromOkHttpResponse(okResponse));
Headers okHeaders = okResponse.headers();
for (int i = 0; i < okHeaders.size(); i++) {
String name = okHeaders.name(i);
String value = okHeaders.value(i);
if (name != null) {
httpResponse.addHeader(new BasicHeader(name, value));
}
}
return httpResponse;
}
@SuppressWarnings("deprecation")
/* package */ private static void setConnectionParametersForRequest( /*HttpURLConnection connection*/
okhttp3.Request.Builder builder, Request<?> request) throws IOException, AuthFailureError {
CUtils.logD("OK","---request url : " + request.getUrl());
switch (request.getMethod()) {
case Request.Method.DEPRECATED_GET_OR_POST:
byte[] postBody = request.getPostBody();
if (postBody != null) {
// connection.setRequestMethod("POST");
// addBody(connection, request, postBody);
builder.post(RequestBody.create(MediaType.parse(request.getPostBodyContentType()), postBody));
}
break;
case Request.Method.GET:
// Not necessary to set the request method because connection defaults to GET but
// being explicit here.
// connection.setRequestMethod("GET");
builder.get();
break;
case Request.Method.DELETE:
// connection.setRequestMethod("DELETE");
builder.delete();
break;
case Request.Method.POST:
// connection.setRequestMethod("POST");
// addBodyIfExists(connection, request);
builder.post(addBodyIfExists(request));
break;
case Request.Method.PUT:
// connection.setRequestMethod("PUT");
// addBodyIfExists(connection, request);
builder.put(addBodyIfExists(request));
break;
case Request.Method.HEAD:
// connection.setRequestMethod("HEAD");
builder.head();
break;
case Request.Method.OPTIONS:
// connection.setRequestMethod("OPTIONS");
builder.method("OPTIONS", null);
break;
case Request.Method.TRACE:
// connection.setRequestMethod("TRACE");
builder.method("TRACE", null);
break;
case Request.Method.PATCH:
// connection.setRequestMethod("PATCH");
// addBodyIfExists(connection, request);
builder.patch(addBodyIfExists(request));
break;
default:
throw new IllegalStateException("Unknown method type.");
}
}
private static @Nullable
RequestBody addBodyIfExists(Request<?> request) throws AuthFailureError {
byte[] body = request.getBody();
if (body == null) {
return null;
}
return RequestBody.create(MediaType.parse(request.getBodyContentType()), body);
}
private static ProtocolVersion parseProtocol(final Protocol protocol) {
switch (protocol) {
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 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;
}
}
致敬大佬,努力前行!