Androidネットワークオープンソースフレームvolly(5)——vollyの詳細


最近またvollyを出して整理しました.前に会ったことのない小さな問題がまた来ました.ここでメモします.
1、HttpUrlConnection DELETE方式ではbodyを追加できない問題:java.net.Protocol Exception:DELETE does not support writing
    これはシステムレベルのバグです.なぜここを見てください.この問題はjava 8で解決されますか?直接行く方法がないので、回り道をします.HttpUrlConnectionを見ると、彼は抽象的なタイプであることが分かりますので、他の実現を通じて目的を達成できるかどうか試してみてもいいです.最終的には私たちはこれを使って実現することにしました.アドレス:https://github.com/square/okhttp.
続いて、私達はvollyのソースコードを見に行きます.私達のアプリ互換の最低バージョンは4.0ですので、最終的に呼び出したのはHurl Stockだと知っています.
    public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
...
        if (stack == null) {
            if (Build.VERSION.SDK_INT >= 9) {
                stack = new HurlStack();
            } else {
                // Prior to Gingerbread, HttpUrlConnection was unreliable.
                // See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
                stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
            }
        }
...
    }
したがって、私たちはHurlStockの関連コードを修正するだけでいいです.
volly.java
public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
...
        if (stack == null) {
            if (Build.VERSION.SDK_INT >= 9) {
                // old way: stack = new HurlStack();
            		// http://square.github.io/okhttp/
                stack = new HurlStack(null, null, new OkUrlFactory(new OkHttpClient()));
            } else {
                // Prior to Gingerbread, HttpUrlConnection was unreliable.
                // See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
                stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
            }
        }
...
    }
Hurl Stock.java
/**
 * An {@link HttpStack} based on {@link HttpURLConnection}.
 */
public class HurlStack implements HttpStack {

    private final OkUrlFactory mOkUrlFactory; 

    /**
     * @param urlRewriter Rewriter to use for request URLs
     * @param sslSocketFactory SSL factory to use for HTTPS connections
     * @param okUrlFactory solution delete body(https://github.com/square/okhttp)
     */
    public HurlStack(UrlRewriter urlRewriter, SSLSocketFactory sslSocketFactory, OkUrlFactory okUrlFactory) {
        mUrlRewriter = urlRewriter;
        mSslSocketFactory = sslSocketFactory;
        mOkUrlFactory = okUrlFactory;
    }
    /**
     * Create an {@link HttpURLConnection} for the specified {@code url}.
     */
    protected HttpURLConnection createConnection(URL url) throws IOException {
		if(null != mOkUrlFactory){
			return mOkUrlFactory.open(url);
		}
        return (HttpURLConnection) url.openConnection();
    }


    @SuppressWarnings("deprecation")
    /* package */ 
    static void setConnectionParametersForRequest(HttpURLConnection connection,
            Request<?> request) throws IOException, AuthFailureError {
        switch (request.getMethod()) {
            ...
            case Method.DELETE:
                connection.setRequestMethod("DELETE");
                addBodyIfExists(connection, request);
                break;
            ...
            default:
                throw new IllegalStateException("Unknown method type.");
        }
    }

...
}
2015-04-26更新:
もう一度使用するには、ok httpを使います.上のコードを振り返ってみますと、当時はどう思っていたか分かりません.こんなに複雑な方法でOkhttpを導入して、頭が水に浸りました.また、この方法を見てください.newrequest Que(Contect context context、HttpStock)には、二つのパラメータがあります.私たちはOKhttpを使って実現します.
/**
 * 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);
  }   
}
参照:https://gist.github.com/JakeWharton/5616899
2、vollyのキャッシュについて
    vollyには完全なキャッシュメカニズムがあります.現在私達は簡単な需要をしたいです.一部のインターフェースは簡単に一定の時間のキャッシュをして、コードを調べてみました.簡単に一つのところを修正します.request.parseNetwork Resonseの中の
HttpHeader Parsser(ここで突然vollyのデザインTMDが柔軟になったと感嘆しました.どう直したらいいですか?)HttpHeader Parsser修正後のコードは以下の通りです.
/**
 *     ,      
 */
public class BHHttpHeaderParser {

    /**
     * Extracts a {@link Cache.Entry} from a {@link NetworkResponse}.
     *
     * @param response The network response to parse headers from
     * @return a cache entry for the given response, or null if the response is not cacheable.
     */
    public static Cache.Entry parseCacheHeaders(NetworkResponse response, boolean isCustomCache) {
...
        if(isCustomCache){
        		softExpire = now + Config.HTTP_CACHE_TTL;
        } else {
	        	if (hasCacheControl) {
	            softExpire = now + maxAge * 1000;
	        } else if (serverDate > 0 && serverExpires >= serverDate) {
	            // Default semantic for Expire header in HTTP specification is softExpire.
	            softExpire = now + (serverExpires - serverDate);
	        }
        }
        
        Cache.Entry entry = new Cache.Entry();
        entry.data = response.data;
        entry.etag = serverEtag;
        entry.softTtl = softExpire;
        entry.ttl = entry.softTtl;
        entry.serverDate = serverDate;
        entry.responseHeaders = headers;

        return entry;
    }
...
}
ここで、私たちは主にカスタム変数によってcacheのTTLをどのように修正するかを決めて自分の目的を達成することができます.
3、HttpUrlConnectionとPATCH(2015-04-26)
Vollyを使用してPATCH要求を送信すると、私たちはこのような問題に出会うかもしれない.must be one of[OPTIONS,GET,HEAD,POST,PUT,DELETE,TRACE]です.この時のあなたの第一反応は何ですか?VollyがPATCH要求をサポートしていないのですか?OkHttpに変えてもいいですか?Vollyのソースコードを確認しました.HurlHttp.javaで次のような一節が見つかりました.
/* package */ 
static void setConnectionParametersForRequest(HttpURLConnection connection,
            Request<?> request) throws IOException, AuthFailureError {
        switch (request.getMethod()) {
            case Method.DEPRECATED_GET_OR_POST:
                // This is the deprecated way that needs to be handled for backwards compatibility.
                // If the request's post body is null, then the assumption is that the request is
                // GET.  Otherwise, it is assumed that the request is a POST.
                byte[] postBody = request.getPostBody();
                if (postBody != null) {
                    // Prepare output. There is no need to set Content-Length explicitly,
                    // since this is handled by HttpURLConnection using the size of the prepared
                    // output stream.
                    connection.setDoOutput(true);
                    connection.setRequestMethod("POST");
                    connection.addRequestProperty(HEADER_CONTENT_TYPE,
                            request.getPostBodyContentType());
                    DataOutputStream out = new DataOutputStream(connection.getOutputStream());
                    out.write(postBody);
                    out.close();
                }
                break;
            case Method.GET:
                // Not necessary to set the request method because connection defaults to GET but
                // being explicit here.
                connection.setRequestMethod("GET");
                break;
            case Method.DELETE:
                connection.setRequestMethod("DELETE");
                break;
            case Method.POST:
                connection.setRequestMethod("POST");
                addBodyIfExists(connection, request);
                break;
            case Method.PUT:
                connection.setRequestMethod("PUT");
                addBodyIfExists(connection, request);
                break;
            case Method.HEAD:
                connection.setRequestMethod("HEAD");
                break;
            case Method.OPTIONS:
                connection.setRequestMethod("OPTIONS");
                break;
            case Method.TRACE:
                connection.setRequestMethod("TRACE");
                break;
            case Method.PATCH:
                connection.setRequestMethod("PATCH");
                addBodyIfExists(connection, request);
                break;
            default:
                throw new IllegalStateException("Unknown method type.");
        }
    }
はこのコードを通して、VollyがPATCHに対してサポートしていることを知っています.よく見てください.これはHttpUrlConnectionが投げたものです.ですから、私たちはこの面で手を打たなければなりません.参考になります.
https://github.com/adriancole/retrofit/commit/e704b800878b2e37f5ac98b0139cb4994618ace0
これからは他のvollyに関するまとめがここに記録されます.