1. 程式人生 > >Android 開源框架 ( 六 ) Volley --- Google的輕量級網絡通信框架

Android 開源框架 ( 六 ) Volley --- Google的輕量級網絡通信框架

quest 緩存 erro jsonarray static 行數據 rmi cif jpg

一.Volley介紹   

  2013年Google I/O大會上推出的一個新的Android網絡通信框架,目標是將HTTP的通信操作再進行簡單化,除了簡單易用之外,Volley在性能方面也進行了大幅度的調整,它的設計目標就是非常適合去進行數據量不大,但通信頻繁的網絡操作,而對於大數據量的網絡操作,比如說下載文件等,Volley的表現就會非常糟糕。

二.Volley使用

1.導入jar包

如果只是用於學習,可以通過gradle引用 compile ‘com.mcxiaoke.volley:library:1.0.19‘ 了解下.但是如果用於項目中,最好下載Google官方的jar包.

compile ‘com.mcxiaoke.volley:library:1.0.19‘  

2.授權

<uses-permission android:name="android.permission.INTERNET" />

3.使用JsonObjectRequest get請求方式示例

        //1.創建一個請求隊列RequestQueue     
        RequestQueue queue= Volley.newRequestQueue(this);
        //2.創建StringRequest對象 
        JsonObjectRequest request=new JsonObjectRequest(url, new Response.Listener<JSONObject>() {
            @Override
            
public void onResponse(JSONObject jsonObject) { //接收返回數據 Log.e("success",jsonObject.toString()); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) { } });
//3.將請求對象添加到請求隊列中 queue.add(request);

  同樣還有一些其他請求:ClearCacheRequest,ImageRequest,JsonArrayRequest,JsonRequest,StringRequest 用法一樣.

        技術分享圖片


      1.ClearCacheRequest :A synthetic request used for clearing the cache. 用於清除緩存請求類
      2.ImageRequest :A canned request for getting an image at a given URL and calling back with a decoded Bitmap. 通過Url獲取對應解碼位圖decoded BitMap 請求類
      3.JsonArrayRequest :A request for retrieving a {@link JSONArray} response body at a given URL. 通過Url返回一個{@ Link JSONArray}Json數組請求類
      4.JsonObjectRequest :A request for retrieving a {@link JSONObject} response body at a given URL, allowing for an optional {@link JSONObject} to be passed in as part of the request body. 可以通過Url返回一個{@link JSONObject},也可以使用{@link JSONObject}當做請求Request的傳遞參數.
      5.JsonRequest :A request for retrieving a T type response body at a given URL that also optionally sends along a JSON body in the request specified. 通過Url返回一個定義的泛型T ,也可以使用JSON當做請求Request的傳遞參數的類
      6.StringRequest :A canned request for retrieving the response body at a given URL as a String. 通過Url返回一個String字符串請求類



  4.使用JsonObjectRequest post請求方式示例

  Post請求,只需要在Request請求裏,添加一個參數Request.Method.POST : new JsonObjectRequest(Request.Method.POST,url, new Response.Listener<JSONObject>() {...});其他部分一樣.

RequestQueue queue= Volley.newRequestQueue(this);
        JsonObjectRequest request=new JsonObjectRequest(Request.Method.POST,url, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject jsonObject) {
                //接收返回數據
                Log.e("success",jsonObject.toString());
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {

            }
        });
        queue.add(request);

  通過Request.Method.能看到Volley支持的一些請求方式:
          技術分享圖片

  5.HurlStack 與 HttpClientStack 介紹

   Volley是官方出的,volley在設計的時候是將具體的請求客戶端做了下封裝,也就是說可以支持HttpUrlConnection, HttpClient.當然也可以自己封裝支持OkHttp.

  Volley.java類

  

  if (stack == null) {
            if (Build.VERSION.SDK_INT >= 9) {
                //HttpURLConnection 請求方式
                stack = new HurlStack();
            } else {
                // Prior to Gingerbread, HttpUrlConnection was unreliable.
                // See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
                //HttpClient 請求方式
                stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
            }
        }

然後具體看下 HurlStack.java 裏的HttpUrlConnection請求封裝.

  /**
     * An {@link HttpStack} based on {@link HttpURLConnection}.
     */
public class HurlStack implements HttpStack {

    private static final String HEADER_CONTENT_TYPE = "Content-Type";
    
    /**
     * Create an {@link HttpURLConnection} for the specified {@code url}.
     */
    protected HttpURLConnection createConnection(URL url) throws IOException {
        return (HttpURLConnection) url.openConnection();
    }

    /**
     * Opens an {@link HttpURLConnection} with parameters.
     * @param url
     * @return an open connection
     * @throws IOException
     */
    private HttpURLConnection openConnection(URL url, Request<?> request) throws IOException {
        HttpURLConnection connection = createConnection(url);

        int timeoutMs = request.getTimeoutMs();
        connection.setConnectTimeout(timeoutMs);
        connection.setReadTimeout(timeoutMs);
        connection.setUseCaches(false);
        connection.setDoInput(true);

        // use caller-provided custom SslSocketFactory, if any, for HTTPS
        if ("https".equals(url.getProtocol()) && mSslSocketFactory != null) {
            ((HttpsURLConnection)connection).setSSLSocketFactory(mSslSocketFactory);
        }

        return connection;
    }

    @SuppressWarnings("deprecation")
    /* 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.");
        }
    }

        private static void addBodyIfExists(HttpURLConnection connection, Request<?> request)
            throws IOException, AuthFailureError {
            byte[] body = request.getBody();
            if (body != null) {
                connection.setDoOutput(true);
                connection.addRequestProperty(HEADER_CONTENT_TYPE, request.getBodyContentType());
                DataOutputStream out = new DataOutputStream(connection.getOutputStream());
                out.write(body);
                out.close();
            }
        }

}    

在看看HttpClientStack.java 裏的HttpClient的封裝. 註意下哈,HttpClient 已經在Android 6.0 刪除.

/**
 * An HttpStack that performs request over an {@link HttpClient}.
 */
public class HttpClientStack implements HttpStack {
    protected final HttpClient mClient;

    private final static String HEADER_CONTENT_TYPE = "Content-Type";
    
    
    /**
     * Creates the appropriate subclass of HttpUriRequest for passed in request.
     */
    @SuppressWarnings("deprecation")
    /* protected */ static HttpUriRequest createHttpRequest(Request<?> request,
            Map<String, String> additionalHeaders) throws 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) {
                    HttpPost postRequest = new HttpPost(request.getUrl());
                    postRequest.addHeader(HEADER_CONTENT_TYPE, request.getPostBodyContentType());
                    HttpEntity entity;
                    entity = new ByteArrayEntity(postBody);
                    postRequest.setEntity(entity);
                    return postRequest;
                } else {
                    return new HttpGet(request.getUrl());
                }
            }
            case Method.GET:
                return new HttpGet(request.getUrl());
            case Method.DELETE:
                return new HttpDelete(request.getUrl());
            case Method.POST: {
                HttpPost postRequest = new HttpPost(request.getUrl());
                postRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType());
                setEntityIfNonEmptyBody(postRequest, request);
                return postRequest;
            }
            case Method.PUT: {
                HttpPut putRequest = new HttpPut(request.getUrl());
                putRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType());
                setEntityIfNonEmptyBody(putRequest, request);
                return putRequest;
            }
            case Method.HEAD:
                return new HttpHead(request.getUrl());
            case Method.OPTIONS:
                return new HttpOptions(request.getUrl());
            case Method.TRACE:
                return new HttpTrace(request.getUrl());
            case Method.PATCH: {
                HttpPatch patchRequest = new HttpPatch(request.getUrl());
                patchRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType());
                setEntityIfNonEmptyBody(patchRequest, request);
                return patchRequest;
            }
            default:
                throw new IllegalStateException("Unknown request method.");
        }
    }
    
}

Android 開源框架 ( 六 ) Volley --- Google的輕量級網絡通信框架