58. SaveVolley

SaveVolley


Save volley from anything, By Agera to save. Thus, derived the AgeraVolley . (。>﹏<。)


gson: 2.7

fastjson: 1.1.52.android

agera: 1.1.0

okhttp3: 3.3.1



savevolley-okhttp3-agera-gson || savevolley-okhttp3-agera-fastjson


savevolley-okhttp3-agera-gson gradle

dependencies {
    compile 'com.google.code.gson:gson:2.7'
    compile 'com.squareup.okhttp3:okhttp:3.3.1'
    compile 'com.google.android.agera:agera:1.1.0'

    // for okhttp3
    compile 'com.camnter.savevolley:okhttp3:1.6.6'
    // for gson
    compile 'com.camnter.savevolley:savevolley-okhttp3-agera-gson:1.6.6'
}

可以使用 SaveVolley Flowagera Flow

    SaveVolley saveVolley = SaveVolleys
        .<GankData>request(TEST_URL)
        .method(Method.GET)
        .parseStyle(GSON)
        .classOf(GankData.class)
        .createRequest()
        .context(this)
        .compile();

    final Repository<GankResultData> repository = Repositories.repositoryWithInitialValue(
        INITIAL_VALUE)
        .observe(saveVolley.getReservoir())
        .onUpdatesPerLoop()
        .goTo(executor)
        .attemptGetFrom(saveVolley.getReservoir())
        .orSkip()
        .thenAttemptTransform(new Function<Object, Result<GankResultData>>() {
            /**
             * Returns the result of applying this function to {@code input}.
             */
            @NonNull @Override public Result<GankResultData> apply(@NonNull Object input) {
                if (input instanceof GankData) {
                    return Result.success(((GankData) input).results.get(0));
                } else if (input instanceof VolleyError) {
                    return Result.failure((VolleyError) input);
                }
                return Result.failure();
            }
        })
        .orSkip()
        .compile();

    repository.addUpdatable(new Updatable() {
        @Override public void update() {
            getContentText.setText(repository.get().toString());
        }
    });


savevolley-okhttp3-agera-fastjson gradle

dependencies {
    compile 'com.alibaba:fastjson:1.1.52.android'
    compile 'com.squareup.okhttp3:okhttp:3.3.1'
    compile 'com.google.android.agera:agera:1.1.0'

    // for okhttp3
    compile 'com.camnter.savevolley:okhttp3:1.6.6'
    // for fastjson
    compile 'com.camnter.savevolley:savevolley-okhttp3-agera-fastjson:1.6.6'
}
    SaveVolley saveVolley = SaveVolleys
        .<GankData>request(TEST_URL)
        .method(Method.GET)
        .parseStyle(FASTJSON)
        .classOf(GankData.class)
        .createRequest()
        .context(this)
        .compile();

    final Repository<GankResultData> repository = Repositories
        .repositoryWithInitialValue(INITIAL_VALUE)
        .observe(saveVolley.getReservoir())
        .onUpdatesPerLoop()
        .goTo(executor)
        .attemptGetFrom(saveVolley.getReservoir())
        .orSkip()
        .thenAttemptTransform(new Function<Object, Result<GankResultData>>() {
            /**
             * Returns the result of applying this function to {@code input}.
             */
            @NonNull @Override public Result<GankResultData> apply(@NonNull Object input) {
                if (input instanceof GankData) {
                    return Result.success(((GankData) input).results.get(0));
                } else if (input instanceof VolleyError) {
                    return Result.failure((VolleyError) input);
                }
                return Result.failure();
            }
        })
        .orSkip()
        .compile();

    repository.addUpdatable(new Updatable() {
        @Override public void update() {
            getContentText.setText(repository.get().toString());
        }
    });



savevolley-hurl-agera-gson || savevolley-hurl-agera-fastjson

可以使用 SaveVolley Flowagera Flow


savevolley-hurl-agera-gson gradle

dependencies {
    compile 'com.google.code.gson:gson:2.7'
    compile 'com.google.android.agera:agera:1.1.0'

    // for hurl
    compile 'com.camnter.savevolley:hurl:1.6.6'
    // for gson
    compile 'com.camnter.savevolley:savevolley-hurl-agera-gson:1.6.6'
}
    SaveVolley saveVolley = SaveVolleys
        .<GankData>request(TEST_URL)
        .method(Method.GET)
        .parseStyle(GSON)
        .classOf(GankData.class)
        .createRequest()
        .context(this)
        .compile();

    final Repository<GankResultData> repository = Repositories.repositoryWithInitialValue(
        INITIAL_VALUE)
        .observe(saveVolley.getReservoir())
        .onUpdatesPerLoop()
        .goTo(executor)
        .attemptGetFrom(saveVolley.getReservoir())
        .orSkip()
        .thenAttemptTransform(new Function<Object, Result<GankResultData>>() {
            /**
             * Returns the result of applying this function to {@code input}.
             */
            @NonNull @Override public Result<GankResultData> apply(@NonNull Object input) {
                if (input instanceof GankData) {
                    return Result.success(((GankData) input).results.get(0));
                } else if (input instanceof VolleyError) {
                    return Result.failure((VolleyError) input);
                }
                return Result.failure();
            }
        })
        .orSkip()
        .compile();

    repository.addUpdatable(new Updatable() {
        @Override public void update() {
            getContentText.setText(repository.get().toString());
        }
    });


savevolley-hurl-agera-fastjson gradle

dependencies {
    compile 'com.alibaba:fastjson:1.1.52.android'
    compile 'com.google.android.agera:agera:1.1.0'

    // for hurl
    compile 'com.camnter.savevolley:hurl:1.6.6'
    // for fastjson
    compile 'com.camnter.savevolley:savevolley-hurl-agera-fastjson:1.6.6'
}
    SaveVolley saveVolley = SaveVolleys
        .<GankData>request(TEST_URL)
        .method(Method.GET)
        .parseStyle(FASTJSON)
        .classOf(GankData.class)
        .createRequest()
        .context(this)
        .compile();

    final Repository<GankResultData> repository = Repositories
        .repositoryWithInitialValue(INITIAL_VALUE)
        .observe(saveVolley.getReservoir())
        .onUpdatesPerLoop()
        .goTo(executor)
        .attemptGetFrom(saveVolley.getReservoir())
        .orSkip()
        .thenAttemptTransform(new Function<Object, Result<GankResultData>>() {
            /**
             * Returns the result of applying this function to {@code input}.
             */
            @NonNull @Override public Result<GankResultData> apply(@NonNull Object input) {
                if (input instanceof GankData) {
                    return Result.success(((GankData) input).results.get(0));
                } else if (input instanceof VolleyError) {
                    return Result.failure((VolleyError) input);
                }
                return Result.failure();
            }
        })
        .orSkip()
        .compile();

    repository.addUpdatable(new Updatable() {
        @Override public void update() {
            getContentText.setText(repository.get().toString());
        }
    });



savevolley-okhttp3-gson || savevolley-okhttp3-fastjson


savevolley-okhttp3-gson gradle

dependencies {
    compile 'com.google.code.gson:gson:2.7'
    compile 'com.squareup.okhttp3:okhttp:3.3.1'

    // for okhttp3
    compile 'com.camnter.savevolley:okhttp3:1.6.6'
    // for gson
    compile 'com.camnter.savevolley:savevolley-okhttp3-gson:1.6.6'
}

可以使用 OkHttp3GsonRequest

    RequestQueue queue = Volley.newRequestQueue(this);
    queue.add(new OkHttp3GsonRequest<GankData>(TEST_URL,
        GankData.class) {
        /**
         * Called when a response is received.
         */
        @Override public void onResponse(GankData response) {
            getContentText.setText(response.toString());
        }


        /**
         * Callback method that an error has been occurred with the
         * provided error code and optional user-readable message.
         */
        @Override public void onErrorResponse(VolleyError error) {
            Toast.makeText(Okhttp3GsonActivity.this,
                error != null && error.getMessage() != null
                ? error.getMessage()
                : "No error message", Toast.LENGTH_LONG)
                .show();
            Log.d("GsonRequest", error != null && error.getMessage() != null
                                 ? error.getMessage()
                                 : "No error message");
        }
    });


savevolley-okhttp3-fastjson gradle

dependencies {
    compile 'com.alibaba:fastjson:1.1.52.android'

    // for okhttp3
    compile 'com.camnter.savevolley:okhttp3:1.6.6'
    // for fastjson
    compile 'com.camnter.savevolley:savevolley-okhttp3-fastjson:1.6.6'
}

可以使用 Okhttp3FastjsonRequest

    RequestQueue queue = Volley.newRequestQueue(this);
    queue.add(new OkHttp3FastjsonRequest<GankData>(TEST_URL, GankData.class) {
        /**
         * Called when a response is received.
         */
        @Override public void onResponse(GankData response) {
            getContentText.setText(response.toString());
        }


        /**
         * Callback method that an error has been occurred with the
         * provided error code and optional user-readable message.
         */
        @Override public void onErrorResponse(VolleyError error) {
            Toast.makeText(Okhttp3FastjsonActivity.this,
                error != null && error.getMessage() != null
                ? error.getMessage()
                : "No error message", Toast.LENGTH_LONG)
                .show();
            Log.d("GsonRequest", error != null && error.getMessage() != null
                                 ? error.getMessage()
                                 : "No error message");
        }
    });



savevolley-hurl-gson || savevolley-hurl-fastjson


savevolley-hurl-gson gradle

dependencies {
    compile 'com.google.code.gson:gson:2.7'

    // for hurl
    compile 'com.camnter.savevolley:hurl:1.6.6'
    // for gson
    compile 'com.camnter.savevolley:savevolley-hurl-gson:1.6.6'
}

可以使用 HurlGsonRequest

    RequestQueue queue = Volley.newRequestQueue(this);
    queue.add(new HurlGsonRequest<GankData>(TEST_URL,
        GankData.class) {
        /**
         * Called when a response is received.
         */
        @Override public void onResponse(GankData response) {
            getContentText.setText(response.toString());
        }


        /**
         * Callback method that an error has been occurred with the
         * provided error code and optional user-readable message.
         */
        @Override public void onErrorResponse(VolleyError error) {
            Toast.makeText(HurlGsonActivity.this,
                error != null && error.getMessage() != null
                ? error.getMessage()
                : "No error message", Toast.LENGTH_LONG)
                .show();
            Log.d("GsonRequest", error != null && error.getMessage() != null
                                 ? error.getMessage()
                                 : "No error message");
        }
    });


savevolley-hurl-fastjson gradle

dependencies {
    compile 'com.alibaba:fastjson:1.1.52.android'

    // for hurl
    compile 'com.camnter.savevolley:hurl:1.6.6'
    // for fastjson
    compile 'com.camnter.savevolley:savevolley-hurl-fastjson:1.6.6'
}

可以使用 HurlFastjsonRequest

    RequestQueue queue = Volley.newRequestQueue(this);
    queue.add(new HurlFastjsonRequest<GankData>(TEST_URL, GankData.class) {
        /**
         * Called when a response is received.
         */
        @Override public void onResponse(GankData response) {
            getContentText.setText(response.toString());
        }


        /**
         * Callback method that an error has been occurred with the
         * provided error code and optional user-readable message.
         */
        @Override public void onErrorResponse(VolleyError error) {
            Toast.makeText(HurlFastjsonActivity.this,
                error != null && error.getMessage() != null
                ? error.getMessage()
                : "No error message", Toast.LENGTH_LONG)
                .show();
            Log.d("GsonRequest", error != null && error.getMessage() != null
                                 ? error.getMessage()
                                 : "No error message");
        }
    });



savevolley-okhttp3


gradle

dependencies {
    // for okhttp3
    compile 'com.camnter.savevolley:okhttp3:1.6.6'
}

savevolley-okhttp3

將 原版的 google/volley 中 網絡實現層 的 Apache HttpClient原生的 HttpUrlConnection 都移除。
換成 square/okhttp3 作爲實現網絡請求。



savevolley-hurl


gradle

dependencies {
    // for hurl
    compile 'com.camnter.savevolley:hurl:1.6.6'
}

API >= 9

savevolley-hurl

移除了 原版 google/volley 中的,所有相關與 HttpClient 的邏輯,全版本的網絡通信接入到 HttpUrlConnection 內。



savevolley-network-core

savevolley-network-core

由於,網絡底層實現( 網絡請求實現 )可以通過不同框架( okhttp、HttpUrlConnection、Apache HttpClient … )去實現。
所以,只是拿到 不同框架的響應結果
但是 Volley 的緩存層是 通用的,所以需要定義一套 通用的 HTTP Response API,然後將 不同框架的響應結果 轉換爲
通用的 HTTP Response API

這個模塊還需要與 savevolley-network-adapter 的子模塊( savevolley-network-okhttp3-adapter, savevolley-network-hurl-adapter )一起協作。



savevolley-network-adapter

savevolley-network-adapter

目的是爲了定義一些接口: 不同框架的響應結果 >> 通用的 HTTP Response API
子模塊有: savevolley-network-okhttp3-adapter, savevolley-network-hurl-adapter



savevolley-network-okhttp3-adapter

savevolley-network-okhttp3-adapter

savevolley-network-adapter 的子模塊,square/okhttp Response >> 通用的 HTTP Response API



savevolley-network-hurl-adapter

savevolley-network-hurl-adapter

savevolley-network-adapter 的子模塊,HttpConnection >> 通用的 HTTP Response API



extensions / savevolley-hurl-agera-core

savevolley-hurl-agera-core

作用: 提供一些 hurlagera 協作需要的基礎類。



extensions / savevolley-okhttp3-agera-core

savevolley-okhttp3-agera-core

作用: 提供一些 okhttp3agera 協作需要的基礎類。



extensions / agera-gson / savevolley-okhttp3-agera-gson

savevolley-okhttp3-agera-gson

作用: agera >> savevolley-okhttp3 << gson , 爲 savevolley-okhttp3 橋接了 ageragson



extensions / agera-gson / savevolley-hurl-agera-gson

savevolley-hurl-agera-gson

作用: agera >> savevolley-hurl << gson , 爲 savevolley-hurl 橋接了 ageragson



extensions / agera-fastjson / savevolley-okhttp3-agera-fastjson

savevolley-okhttp3-agera-fastjson

作用: agera >> savevolley-okhttp3 << fastjson , 爲 savevolley-okhttp3 橋接了 agerafastjson



extensions / agera-fastjson / savevolley-hurl-agera-fastjson

savevolley-hurl-agera-fastjson

作用: agera >> savevolley-hurl << fastjson , 爲 savevolley-hurl 橋接了 agerafastjson



extensions / fastjson / savevolley-hurl-fastjson

savevolley-hurl-fastjson

作用: fastjson >> savevolley-hurl



extensions / fastjson / savevolley-okhttp3-fastjson

savevolley-okhttp3-fastjson

作用: fastjson >> savevolley-okhttp3



extensions / gson / savevolley-hurl-gson

savevolley-hurl-gson

作用: gson >> savevolley-hurl



extensions / gson / savevolley-okhttp3-gson

savevolley-okhttp3-gson

作用: gson >> savevolley-okhttp3



square-okhttp3

square/okhttp Version: 3.3.1



google-agera

google/agera Version: 1.1.0-beta2



volley-comments

volley-comments

原版的 google/volley,全部代碼加上了註釋。


入口

Volley:Volley 框架使用的入口,用於創建一個 RequestQueue。

  • 1. RequestQueue queue = Volley.newRequestQueue(this)

  • 2. queue.add(request)

RequestQueueRequestQueue 被定義爲 請求隊列。用於操作 緩存請求執行線程( CacheDispatcher )和 網絡請求執行線程( NetworkDispatcher )。默認的情況下:

  • 1. 啓動 1 個 緩存請求執行線程( CacheDispatcher )。

  • 2. 根據 DEFAULT_NETWORK_THREAD_POOL_SIZE 的值,啓動 4 個 網絡請求執行線程( NetworkDispatcher )。

  • 3. 這些線程共享 緩存請求隊列 ( mCacheQueue )和 網絡請求隊列( mNetworkQueue ),當 RequestQueue 進行 請求的 添加、結束時,都會進入同步操作,保證線程安全。所以,RequestQueue 進行 請求的 添加、結束。是直接影響 CacheDispatcher 和 NetworkDispatcher 的執行


核心 異步

NetworkDispatcher:是用於處理 Volley 中的網絡請求 的 網絡線程,會將 網絡 Request 隊列的 Request 逐個抽出,然後進行網絡請求:

  • 1. 成功,拿到數據進行解析,然後將 Response 進行硬盤緩存,緩存成 Cache.Entry 的形式,最後 傳遞 RequestResponse 數據。

  • 2. 失敗,失敗的話,一般會拋出異常,然後進行 記錄請求時長傳遞錯誤( VolleyError )

CacheDispatcher:是用於處理 Volley 中的緩存數據 的 緩存線程

  • 1.1. 檢查緩存。從 緩存 Request 隊列中取出 緩存 Request,然後 根據 緩存 Request CacheKey 去硬盤緩存( DiskBasedCache )映射過來的內存緩存中尋找 是否存在 EntryResponse )。

  • 1.2. 存在的話,通過 DefaultRetryPolicy 回傳相關數據。

  • 1.3. 存在但緩存需要刷新的話,放入 網絡 Request 隊列 內,會在 NetworkDispatcher 的循環體中被用來 重新請求

  • 1.4. 不存在的話,將該 Request,放入 網絡 Request 隊列 內,會在 NetworkDispatcher 的循環體中被用來 重新請求

  • 2. CacheDispatcher 只做緩存相關的操作,不做網絡的操作。所以 CacheDispatcher只涉及到 緩存 Response 的增刪改查 以及 查詢成功後的數據分發( 傳遞 )


網絡請求 使用層

Network:在 Volley 中,是處理 網絡請求 的表層使用接口。只有一個方法:performRequest(...) 執行請求,

BasicNetworkBasicNetwork 是 目前 Volley 內,Network 接口的唯一實現類,在 Volley 內,處理了 網絡請求 的表層使用接口。實現了 performRequest(...) 方法的具體功能,performRequest(...) 要做的事情是

  • 1. 調用 HttpStack 接口的實現類 ( HurlStack, HttpClientStack ) 去執行網絡請求實現,會拿到一個 Apache HttpResponse

  • 2. 然後,將 Apache HttpResponse -> Volley NetworkResponse 進行轉化,並返回。


網絡請求 實現層

HttpStackHttpStack 是 Volley 內 執行 網絡請求 的 底層實現接口。實現類有:

  • 1. HttpClientStack:基於 org.apache.http 的網絡請求實現。負責 系統版本 2.3 以下 的 網絡請求實現。

  • 2. HurlStack:基於 HttpURLConnection 的網絡請求實現。負責 系統版本 2.3 以上 的 網絡請求實現。

HttpClientStackHttpClientStack 實現了 HttpStack 接口。封裝了基於 org.apache.http.HttpClient 提供的網絡實現( performRequest(...) ),處理了 2.3 版本以下的 各種網絡請求( GET、POST、DEL … )的實現

HurlStackHurlStack 實現了 HttpStack 接口。封裝了基於 javax.net.ssl.HttpsURLConnection 提供的網絡實現( performRequest(...) ),處理了 2.3 版本以上的 各種網絡請求( GET、POST、DEL … )的實現


請求( Request )

Request:Volley 內所有抽象請求的 基類

StringRequest:繼承擴展了 Request,指定了泛型爲 <String>。會將請求結果解析成 String 類型數據,並且 需要你 傳入一個 Response.Listener<String> 進行解析結果數據進行回調。

JsonRequestJsonRequest<T> 抽象繼承了 Request<T> 類。

  • 1. 進行了Request<T> -> JsonRequest<T> 的轉換。

  • 2. 將請求結果數據 根據 “charset=utf-8” 轉換爲 byte[]

  • 3. 通過覆寫 getBodyContentType() 方法,將 Content-Type 設置爲 application/json; charset=utf-8

JsonObjectRequestJsonObjectRequest 繼承自 JsonRequest<JSONObject>,將 JsonRequest<T> 的泛型 T,設置爲 JSONObjectJsonRequest<T> 沒有解析 body 內的數據爲 真正的 Json 數據。所以,JsonObjectRequest 要單獨將 body 內的數據解析爲 JSONObject類型。

JsonArrayRequestJsonArrayRequest 繼承自 JsonRequest<JSONArray>,將 JsonRequest<T> 的泛型 T,設置爲 JSONArrayJsonRequest<T> 沒有解析 body 內的數據爲 真正的 Json 數據。所以,JsonArrayRequest 要單獨將 body 內的數據解析爲 JSONArray 類型。

ImageRequest:繼承擴展了 Request,指定了泛型爲 <Bitmap>,會將請求結果解析成 Bitmap 類型數據。並且需要你傳入:

  • 1. Response.Listener<Bitmap>:將解析結果數據 進行回調。

  • 2. maxWidth:最大寬度。

  • 3. maxHeight:最大高度。

  • 4. ScaleTypeImageViewScaleType( CENTER_CROP, FIT_XY … )。

  • 5. ConfigBitmapConfig ( ALPHA_8, RGB_565, ARGB_4444, ARGB_8888 )。

  • 6. Response.ErrorListener:請求結果 Response 發生錯誤的回調接口。

ClearCacheRequestClearCacheRequest 繼承自 Request<Object>,用於清空 HTTP 緩存的請求。如果該請求被添加到 請求隊列( RequestQueue )中,由於覆寫了 getPriority() 方法,將優先級設置爲 Priority.IMMEDIATE ( 立即執行 )


響應( Response )

Response:請求結果(響應)類。

  • 1. 存放 請求結果數據緩存 key;或者 錯誤信息( VolleyError )

  • 2. 提供一個 Listener 接口。當接受到 請求結果(響應)時,將 解析結果 返回。

  • 3. 再提供一個 ErrorListener 接口。發生錯誤時,將調用該方法,將返回 VolleyError

  • 4. 提供一個靜態方法 success(...),實例一個有 請求結果數據Response 對象

  • 5. 再提供一個靜態方法 error(...),實例一個只有 錯誤信息( VolleyError )Response 對象


緩存

Cache:Volley 緩存的接口。提供一些接口方法,需要子類去實現,全 Volley 中主要實現類,只有一個 DiskBasedCache

DiskBasedCacheDiskBasedCacheCache 的實現類。用於將保存緩存文件在硬盤上的指定目錄中,默認的緩存大小是 5MB,緩存大小是可以手動配置的。

  • 1. 實例化了一個 LinkedHashMap<String, CacheHeader>accessOrder 設置爲 true。即,按照訪問順序對數據進行排序,就是 LRU 的簡單時間。容量 initialCapacity 爲默認值 16,雖然手動寫了 16。負載因子 loadFactor 默認值 0.75f,雖然手動寫了 0.75。負載因子是 當容量超過這個百分比就會擴容,0.75f 的話,就是容量超過75%就會擴容。

  • 2.initialize() 的時候:<1>.:判斷緩存目錄是否存在,不存在則創建一系列文件夾,然後返回。<2>.:存在緩存文件,開始讀取緩存文件內容。每一個緩存文件內容對應一個 CacheHeader。會給上述的 LinkedHashMap<String, CacheHeader>CacheHeader 緩存的內容進行添加,把文件緩存的內容映射過來。

NoCache:繼承了 Cache,不做任何操作的緩存實現類。可以作爲 RequestQueue 構造方法的參數,實現一個不帶緩存的請求隊列。


數據傳遞(分發)

ResponseDeliveryResponseDelivery 接口的作用 -> 從 內存緩存 或者 服務器 取得請求結果數據,由 ResponseDelivery 去做結果分發以及回調處理。

ExecutorDeliveryExecutorDelivery 實現了 ResponseDelivery 接口。
主要功能就是:

  • 1. 傳遞 請求、請求結果 or 相應錯誤 以及 可能有自定義的 Runnable 執行回調操作。

  • 2. 定義了一個 Executor,因爲可能會有自定義的 Runnable 執行回調操作,所以需要它的存在。

  • 3. 因爲有 ExecutorRunnable 的存在,但是都在子線程內。所以,還需要傳入一個 UI 線程的 Handler(大多情況回調都是跟 UI 線程通信),可以在 RequestQueue 類中 搜搜 new Handler(Looper.getMainLooper()) 關鍵句。

構造方法也是有趣設計:

  • 1. Handler 作爲參數的構造方法。全 Volley 只有 RequestQueue 內使用,並且傳入一個 UI 線程的 Handler。可以簡單得出:這個構造方法可以指定( 不只是 UI 線程 )線程的 Handler 去處理這個 Runnable。看過 Handler 源碼的都知道:你給我一個 Runnable,我會 拿到這個 Handler 實例化時的 Looper。再拿到 MessageQueue 去添加一條 MessageRunnable 則作爲 這個 Message.callback 保存在這,然後再 Handler.dispatchMessage(…) 的時候,會執行 Message.callback.run()。所以,這裏(不只是 UI 線程)線程的 Handler,說明了可以給其他線程傳遞( 通信 )。

  • 2. Executor 作爲參數的構造方法。這裏由於 Executor 作爲外部提供的參數,那麼 Handler 也在外面提供了,更具有可定製性。Handler作爲參數的構造方法 就是 這個 Executor 作爲參數的構造方法 的升級版。因爲,ExecutorDelivery 需要 ExecutorHandlerHandler 作爲參數的構造方法:實例化了 ExecutorHandler 由外部提供,這裏 Executor 是默認執行 handler.post(Runnable command)Executor 作爲參數的構造方法:都需要外部提供。


工具

HttpHeaderParserHttp header 的解析工具類。

  • 1. 解析 Header,判斷返回結果是否需要緩存。需要緩存的話,從網絡請求回來的請求結果 NetworkResponseHeader 中提取出一個用於緩存的 Cache.Entry

  • 2. 解析編碼集,在 Content-Type 中獲取編碼集( charset ),可以根據 編碼 解析 Response.databyte[] 數據。

RequestFutureRequestFuture<T> 實現了 Future<T> 接口,用於對 Request 解析數據的結果 進行 取消查詢是否完成獲取結果


byte[] 流和緩存池

ByteArrayPool:一個 byte[] 緩存池,用於 byte[] 的回收再利用,減少內存分配和回收。

  • 1. 內置一個 LinkedList, 採用 LRU 的機制,最少使用的放在 index=0,最近使用的 放在 index=size()-1

  • 2. 再內置一個 LinkedList,緩存 byte[] 緩存 List,採用根據 byte[].length 由小到大的方式排序。排序使用 Collections.binarySearch(...),對應 Comparator<byte[]> BUF_COMPARATOR

PoolingByteArrayOutputStreamPoolingByteArrayOutputStream 繼承了 原生的 ByteArrayOutputStream,使用了 ByteArrayPool 回收利用一些 byte[],防止了 byte[] 的重複內存分配和回收。


重試策略

RetryPolicy:重試策略接口。具體實現可以自定義,也有默認的 DefaultRetryPolicy

DefaultRetryPolicyDefaultRetryPolicy 繼承自 RetryPolicy注意的地方就是 -> mBackoffMultiplierDEFAULT_BACKOFF_MULT 用於設置 退避乘數,跟 “指數退避” 有關。


日誌

VolleyLogVolleyLog 是 Volley 的一個工具類。根據 Log.isLoggable(String tag,int level) 設置 Log 的開關。
level >= INFOisLoggable 返回 true,反之則返回 false,所以,開關 默認 關閉。

  • public static final int VERBOSE = 2

  • public static final int DEBUG = 3

  • public static final int INFO = 4

  • public static final int WARN = 5

  • public static final int ERROR = 6

  • public static final int ASSERT = 7

MarkerLog:VolleyLog 提供的一個簡單的靜態內部 Log 類。可以通過 add(...) 添加一個 MarkerLog 的 Log 單位( Marker ),然後調用 finish(...) 打印已經添加的所有 Log。


認證

Authenticator:一個身份認證接口,用於基本認證或者摘要認證。在 Volley 內,是用於和身份認證,比如 OAuth。

AndroidAuthenticator:實現了 Authenticator 接口,基於 Android 上的 AccountManager,實現了認證交互。


錯誤類型

VolleyError:所有 Volley 錯誤的基類。繼承自 Exception,用於描述 Volley 中所有的錯誤異常,可以設置 NetworkResponse 和 請求消耗時間。

AuthFailureErrorAuthFailureError 繼承了 VolleyError。表示:請求認證失敗錯誤,如 RespondCode 的 401 和 403

TimeoutErrorTimeoutError 繼承了 VolleyError。表示:請求超時錯誤。但是什麼都沒有實現,作爲一個標識存在。

ServerErrorServerError 繼承了 VolleyError。表示:服務端錯誤

ClientErrorClientError 擴展了 ServerError 的概念。表示:客戶端錯誤,即 4xx 錯誤

ParseErrorParseError 繼承了 VolleyError。表示:內容解析錯誤

NoConnectionErrorNoConnectionError 繼承了 NetworkError。表示:網絡連接錯誤

NetworkErrorNetworkError 繼承了 VolleyError,表示:網絡錯誤



License

  Copyright (C) 2016 CaMnter [email protected]
  Copyright (C) 2015 Google Inc. All Rights Reserved.
  Copyright (C) 2012 Square, Inc.
  Copyright (C) 2011 The Android Open Source Project
  Copyright (C) 2008 The Apache Software Foundation (ASF)
  Copyright (C) 2007 The Guava Authors

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章