XDroidRequest網絡請求框架,新開源

XDroidRequest 是一款網絡請求框架,它的功能也許會適合你。這是本項目的第三版了,前兩版因爲擴展性問題一直不滿意,思考來 思考去仍是以爲Google的Volley的擴展性最強,因而借鑑了Volley的責任鏈模式,因此有了這個第三版.php

Provide

1 適配 Android 6.0 ,再也不使用HttpClient相關API
2 一行代碼發送請求,提供多種回調函數供選擇,
3 支持8種網絡請求方式 GET,POST,PUT,DELETE,HEAD,OPTIONS,TRACE,PATCH
4 支持請求的優先級設置,優先級高的將先於優先級低的發送請求
5 支持取消請求,能夠取消當前已發送的請求(可自定義取消請求的依據條件),也能夠取消請求隊列中還未發送的請求
6 支持多請求併發,多個請求同時發送,底層使用固定數量線程池,可設置線程池的大小
7 支持重複請求的判斷,當有重複的請求將掛起,等待第一個請求完成後,掛起的請求使用已經請求完畢的緩存,若是未開啓緩存,則會繼續請求網絡
8 支持請求失敗重試,默認重試2次,重試超時時間會遞增,遞增速率可設置,默認爲1倍遞增
9 支持多文件與大文件上傳,能夠與參數一塊兒發送至服務器,提供上傳進度回調
10 支持大文件下載,提供下載進度回調
11 支持發送JSON數據
12 自動網絡斷定,可設置此時是否顯示緩存數據
13 請求結果自動解析,可泛型任何JAVA BEAN,默認實現了GSON解析,可自定義
14 多種錯誤類型斷定
15 擴展性強,可自定義發送請求方式與解析請求結果
16 支持強大的緩存控制
17 支持緩存配置,可配置磁盤緩存路徑,磁盤緩存最大值,磁盤緩存當前佔有大小,磁盤緩存清理
內存緩存最大值大小,內存緩存清理
18 支持緩存管理與控制,包括本地請求緩存一系列信息查詢以及對緩存的手動操做

About cache

1 XDroidRequest使用了二級緩存,內存緩存與磁盤緩存,內存緩存使用LruCache,磁盤緩存使用DiskLruCache
2 setShouldCache(true) ,一個開關控制是否使用緩存的功能
3 setUseCacheDataAnyway(false), 是否老是使用緩存,這個開關開啓後,將每次首先從內存和本地查找緩存,有的話直接使用緩存,
請求會在後臺執行,完成後會更新緩存。若是沒有緩存將直接進行網絡請求獲取,完成後會更新緩存.
4 setUseCacheDataWhenRequestFailed(true) ,是否在請求失敗後使用緩存數據,無網絡屬於請求失敗,能夠保證即便沒有網絡,或者
請求也有數據展現.
5 setUseCacheDataWhenTimeout(true) ,是否在請求超時後直接使用緩存,這裏的超時時間並非網絡請求的超時時間,而是咱們
設定一個時間,超過這個時間後,無論請求有沒有完成都直接使用緩存,後臺的請求完成後會自動更新緩存
6 setUseCacheDataWhenUnexpired(true),是否使用緩存當緩存未過時的時候,這個開關也是常常開啓的開關,每一個緩存都會對應一個過時
時間,先從內存查找緩存,沒有的話再從磁盤查找,有緩存且過時的話,將直接使用緩存數據,當過時以後會進行網絡請求,請求完成後會更新
內存緩存與磁盤。沒有緩存將直接進行網絡請求,請求完成後會更新內存與磁盤緩存
7 setRetryWhenRequestFailed(true) ,是否進行重試,當請求失敗的時候,默認開啓,重試2次,不須要重試功能的話可關閉
8 setNeverExpired(false); 設置緩存是否永不過時 

Here is the sample

Download demo.apkjava

Screenshot

\ \

Usage

1.初始化,應用啓動的時候進行,主要初始化緩存的路徑等信息數據庫

XRequest.initXRequest(getApplicationContext());

2.發起請求api

① GET請求緩存

/**
         * 簡單的Get請求
         * @param mRequestTag 請求的tag,可根據此tag取消請求
         * @param url 請求地址
         * @param OnRequestListener 請求結果回調
         */
        XRequest.getInstance().sendGet(mRequestTag, url, new OnRequestListenerAdapter<String>() {
            @Override
            public void onDone(Request<?> request, Map<String, String> headers, String result, DataType dataType) {
                super.onDone(request, headers, result, dataType);
            }
        });

② POST請求服務器

String url = "http://apis.baidu.com/heweather/weather/free";
RequestParams params = new RequestParams();
params.putHeaders("apikey", "能夠到apistore申請");
params.putParams("city", "hefei");

XRequest.getInstance().sendPost(mRequestTag, url,  params, new OnRequestListenerAdapter<String>() {

    @Override
    public void onRequestFailed(Request<?> request, HttpException httpException) {
        super.onRequestFailed(request, httpException);
        switch (httpException.getHttpErrorCode()) {
        case HttpError.ERROR_NOT_NETWORK:
            Toast.makeText(context, "網絡未鏈接,請檢查", Toast.LENGTH_SHORT).show();
            break;
        }
    }

    @Override
    public void onRequestRetry(Request<?> request, int currentRetryCount, HttpException previousError) {
        Toast.makeText(context, "獲取信息失敗,系統已經爲您重試" + currentRetryCount+"次", Toast.LENGTH_SHORT).show();

        CLog.i("POST請求結果失敗,正在重試,當前重試次數:" + currentRetryCount);
    }

    @Override
    public void onRequestDownloadProgress(Request<?> request, long transferredBytesSize, long totalSize) {
        CLog.i("onRequestDownloadProgress current:%d , total : %d" ,transferredBytesSize,totalSize);
    }

    @Override
    public void onRequestUploadProgress(Request<?> request, long transferredBytesSize, long totalSize, int currentFileIndex,
            File currentFile) {
        CLog.i("onRequestUploadProgress current:%d , total : %d" ,transferredBytesSize,totalSize);
    }

    @Override
    public void onDone(Request<?> request, Map<String, String> headers, String result, DataType dataType) {
        super.onDone(request, headers, result, dataType);
    }
});

③ 發送JSON字符串參數網絡

RequestParams params = new RequestParams();
params.putParams(
        "{\"uid\":863548,\"stickys\":[{\"id\":29058,\"iid\":0,\"content\":\"內容\",\"color\":\"green\",\"createtime\":\"2015-04-16 16:26:17\",\"updatetime\":\"2015-04-16 16:26:17\"}]}");
XRequest.getInstance().sendPost(mRequestTag, url, params, new OnRequestListenerAdapter<String>() {
    @Override
    public void onDone(Request<?> request, Map<String, String> headers, String result, DataType dataType) {
        super.onDone(request, headers, result, dataType);
    }
});

④上傳文件併發

String url = "http://192.168.1.150/upload_multi.php";
RequestParams params = new RequestParams();
params.put("file[0]", new File(Environment.getExternalStorageDirectory().getAbsolutePath(), "app-debug.apk"));
params.put("file[1]", new File(Environment.getExternalStorageDirectory().getAbsolutePath(), "photoview.apk"));
params.putParams("file_name", "上傳的文件名稱");

XRequest.getInstance().upload(mRequestTag, url,  params, new OnRequestListenerAdapter<String>() {

    @Override
    public void onRequestPrepare(Request<?> request) {
        Toast.makeText(context, "請求準備", Toast.LENGTH_SHORT).show();
        CLog.i("請求準備");
    }

    @Override
    public void onRequestFailed(Request<?> request,HttpException httpException) {
        Toast.makeText(context, "請求結果失敗", Toast.LENGTH_SHORT).show();
        CLog.i("請求結果失敗");
    }

    @Override
    public void onRequestRetry(Request<?> request, int currentRetryCount, HttpException previousError) {
        Toast.makeText(context, "獲取信息失敗,系統已經爲您重試" + currentRetryCount+"次", Toast.LENGTH_SHORT).show();

        CLog.i("請求結果失敗,正在重試,當前重試次數:" + currentRetryCount);
    }

    @Override
    public void onRequestUploadProgress(Request<?> request, long transferredBytesSize, long totalSize, int currentFileIndex,
            File currentFile) {
        CLog.i("正在上傳第%s個文件,當前進度:%d , 總大小 : %d" ,currentFileIndex,transferredBytesSize,totalSize);

        mUploadProgressBar.setMax((int) totalSize);
        mUploadProgressBar.setProgress((int) transferredBytesSize);
    }
    @Override
    public void onDone(Request<?> request, Map<String, String> headers, String response, DataType dataType) {
        Toast.makeText(context, "請求完成", Toast.LENGTH_SHORT).show();
    }


});

測試了上傳百兆以上文件無壓力,若是你想測試多文件上傳,下面的PHP多文件上傳代碼供參考。要注意的是PHP默認上傳2M之內文件,須要本身改下 配置文件,網上不少,搜索便可app

<?php
 foreach($_FILES['file']['error'] as $k=>$v)
 {
    $uploadfile = './upload/'. basename($_FILES['file']['name'][$k]);
    if (move_uploaded_file($_FILES['file']['tmp_name'][$k], $uploadfile)) 
    {
        echo "File : ", $_FILES['file']['name'][$k] ," is valid, and was successfully uploaded.\n";
    }

    else 
    {
        echo "Possible file : ", $_FILES['file']['name'][$k], " upload attack!\n";
    }   

 }

 echo "成功接收附加字段:". $_POST['file_name'];

?>

⑤下載文件框架

String url = "http://192.168.1.150/upload/xiaokaxiu.apk";
String downloadPath = "/sdcard/xrequest/download";
String fileName = "test.apk";
XRequest.getInstance().download(mRequestTag, url, downloadPath,fileName, new OnRequestListenerAdapter<File>() {
    @Override
    public void onRequestDownloadProgress(Request<?> request, long transferredBytesSize, long totalSize) {
        CLog.i("正在下載, 當前進度:%d , 總大小 : %d" ,transferredBytesSize,totalSize);
        mDownloadProgressBar.setMax((int) totalSize);
        mDownloadProgressBar.setProgress((int) transferredBytesSize);
    }
    @Override
    public void onDone(Request<?> request, Map<String, String> headers, File result, DataType dataType) {
        CLog.i("下載完成 : %s",result != null?result.toString():"獲取File爲空");
    }
});

⑥關於回調

請求回調OnRequestListener,回調函數不少,根據本身需求選擇性複寫便可,傳入OnRequestListener默認實現類OnRequestListenerAdapter便可

XRequest.getInstance().sendGet(mRequestTag, url, cacheKey, params, new OnRequestListener<String>() {

            /**
             * 請求前準備回調
             * 運行線程:主線程
             * @param request 當前請求對象
             */
            @Override
            public void onRequestPrepare(Request<?> request) {
                Toast.makeText(context, "GET請求準備", Toast.LENGTH_SHORT).show();

                CLog.i("GET請求準備");
            }

            /**
             * 請求完成回調
             * 運行線程:主線程
             * @param request 當前請求對象
             * @param headers 請求結果頭文件Map集合
             * @param result 請求結果泛型對象
             */
            @Override
            public void onRequestFinish(Request<?> request, Map<String, String> headers, String result) {
                Toast.makeText(context, "GET請求結果獲取成功", Toast.LENGTH_SHORT).show();
                CLog.i("GET請求結果獲取成功");
            }

            /**
             * 請求失敗回調
             * 運行線程:主線程
             * @param request 當前請求對象
             * @param httpException 錯誤類對象,包含錯誤碼與錯誤描述
             */
            @Override
            public void onRequestFailed(Request<?> request, HttpException httpException) {
                Toast.makeText(context, "GET請求結果失敗", Toast.LENGTH_SHORT).show();
                CLog.i("GET請求結果失敗");
            }

            /**
             * 請求失敗重試回調
             * 運行線程:主線程
             * @param request 當前請求對象
             * @param currentRetryCount 當前重試次數
             * @param previousError 上一個錯誤類對象,包含錯誤碼與錯誤描述
             */
            @Override
            public void onRequestRetry(Request<?> request, int currentRetryCount, HttpException previousError) {
                Toast.makeText(context, "獲取信息失敗,系統已經爲您重試" + currentRetryCount+"次", Toast.LENGTH_SHORT).show();

                CLog.i("GET請求結果失敗,正在重試,當前重試次數:" + currentRetryCount);
            }

            /**
             * 下載進度回調
             * 運行線程:子線程
             * @param request 當前請求對象
             * @param transferredBytesSize 當前下載大小
             * @param totalSize 總大小
             * 
             */
            @Override
            public void onRequestDownloadProgress(Request<?> request, long transferredBytesSize, long totalSize) {
                CLog.i("onRequestDownloadProgress current:%d , total : %d" ,transferredBytesSize,totalSize);
            }

            /**
             * 上傳進度回調
             * 運行線程:子線程
             * @param request 當前請求對象
             * @param transferredBytesSize 當前寫入進度
             * @param totalSize 總進度
             * @param currentFileIndex 當前正在上傳的是第幾個文件
             * @param currentFile 當前正在上傳的文件對象
             * 
             */
            @Override
            public void onRequestUploadProgress(Request<?> request, long transferredBytesSize, long totalSize, int currentFileIndex,
                    File currentFile) {
                CLog.i("onRequestUploadProgress current:%d , total : %d" ,transferredBytesSize,totalSize);
            }

            /**
             * 緩存數據加載完成回調
             * 運行線程:主線程
             * @param request 當前請求對象
             * @param headers 緩存的頭信息Map集合
             * @param result 緩存的數據結果對象
             */
            @Override
            public void onCacheDataLoadFinish(Request<?> request, Map<String, String> headers, String result) {
                Toast.makeText(context, "GET請求緩存加載成功", Toast.LENGTH_SHORT).show();
                CLog.i("GET請求緩存加載成功");
            }

            /**
             * 解析網絡數據回調,請求完成後,若是須要作耗時操做(好比寫入數據庫)可在此回調中進行,不會阻塞UI
             * 運行線程:子線程
             * @param request 當前請求對象
             * @param networkResponse 網絡請求結果對象,包含byte數據流與頭信息等
             * @param result 解析byte數據流構建的對象
             */
            @Override
            public void onParseNetworkResponse(Request<?> request, NetworkResponse networkResponse, String result) {
                CLog.i("GET請求網絡數據解析完成");
            }

            /**
             * 此請求最終完成回調,每次請求只會調用一次,不管此請求走的緩存數據仍是網絡數據,最後交付的結果走此回調
             * 運行線程:主線程
             * @param request 當前請求對象
             * @param headers 最終交付數據的頭信息
             * @param result 最終交付的請求結果對象
             * @param dataType 最終交付的數據類型枚舉,網絡數據/緩存數據
             */
            @Override
            public void onDone(Request<?> request, Map<String, String> headers, String result, DataType dataType) {
                Toast.makeText(context, "GET請求完成", Toast.LENGTH_SHORT).show();
            }

        });

下面是選擇性複寫回調函數

String url = "http://apis.baidu.com/heweather/weather/free";
        RequestParams params = new RequestParams();
        params.putHeaders("apikey", "能夠到apistore申請");
        params.putParams("city", "hefei");

        String cacheKey = url + "post";  //與GET請求的URL同樣,爲了不一樣的緩存key、這裏從新指定緩存key
        XRequest.getInstance().sendPost(mRequestTag, url, cacheKey, params, new OnRequestListenerAdapter<String>() {

            @Override
            public void onRequestFailed(Request<?> request, HttpException httpException) {
                super.onRequestFailed(request, httpException);
                switch (httpException.getHttpErrorCode()) {
                case HttpError.ERROR_NOT_NETWORK:
                    Toast.makeText(context, "網絡未鏈接,請檢查", Toast.LENGTH_SHORT).show();
                    break;
                }
            }

            @Override
            public void onRequestRetry(Request<?> request, int currentRetryCount, HttpException previousError) {
                Toast.makeText(context, "獲取信息失敗,系統已經爲您重試" + currentRetryCount+"次", Toast.LENGTH_SHORT).show();

                CLog.i("POST請求結果失敗,正在重試,當前重試次數:" + currentRetryCount);
            }

            @Override
            public void onRequestDownloadProgress(Request<?> request, long transferredBytesSize, long totalSize) {
                CLog.i("onRequestDownloadProgress current:%d , total : %d" ,transferredBytesSize,totalSize);
            }

            @Override
            public void onRequestUploadProgress(Request<?> request, long transferredBytesSize, long totalSize, int currentFileIndex,
                    File currentFile) {
                CLog.i("onRequestUploadProgress current:%d , total : %d" ,transferredBytesSize,totalSize);
            }

            @Override
            public void onDone(Request<?> request, Map<String, String> headers, String result, DataType dataType) {
                super.onDone(request, headers, result, dataType);
            }
        });

    }

⑦自動解析

String url = "http://apis.baidu.com/apistore/aqiservice/citylist";
RequestParams params = new RequestParams();
params.putHeaders("apikey", "能夠到apistore申請");
XRequest.getInstance().sendPost(mRequestTag, url, params, CityRootBean.class, new OnRequestListenerAdapter<CityRootBean<CityBean>>() {

    @Override
    public void onDone(Request<?> request, Map<String, String> headers, CityRootBean<CityBean> result,
            DataType dataType) {
        CLog.i("Bean信息:" + (result == null ? "null" : result.toString()));
    }
});

⑧緩存配置

(1)初始化的時候若是想要指定緩存路徑,大小等信息,可參照以下代碼

public class App extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        configXReqeustCache();

    }

    @SuppressLint("SdCardPath")
    private void configXReqeustCache() {
        //磁盤緩存路徑
        File DISK_CACHE_DIR_PATH = new File("/sdcard/xrequest/diskcache");
        //磁盤緩存最大值
        int DISK_CACHE_MAX_SIZE = 30*1024*1024;

        //XRequest.initXRequest(getApplicationContext());

        XRequest.initXRequest(getApplicationContext(), DISK_CACHE_MAX_SIZE, DISK_CACHE_DIR_PATH);
    }
}

(2)查找當前緩存數據佔用的空間

long diskCacheCurrentSize = RequestCacheManager.getInstance().getAllDiskCacheSize();

(3)查找緩存路徑

String diskCacheDir = RequestCacheManager.getInstance().getDiskCacheDirectory().getPath();

(4)查詢當前緩存最大值

long diskCacheMaxSize = RequestCacheManager.getInstance().getDiskCacheMaxSize();

(5)清除全部緩存

RequestCacheManager.getInstance().deleteAllDiskCacheData();

⑨請求配置

在發送請求的時候,有的重載函數須要傳入一個RequestCacheConfig對象,不須要傳入此對象的重載函數內部傳入的是默認的 RequestCacheConfig對象,經過RequestCacheConfig對象控制緩存於網絡數據等,下面是默認的RequestCacheConfig配置

public static RequestCacheConfig buildDefaultCacheConfig() {
RequestCacheConfig cacheConfig=new RequestCacheConfig();
    cacheConfig.setShouldCache(true);  //開啓緩存
    cacheConfig.setUseCacheDataAnyway(false);  //關閉老是優先使用緩存
    cacheConfig.setUseCacheDataWhenRequestFailed(true); //開啓請求失敗使用緩存
    cacheConfig.setUseCacheDataWhenTimeout(false); //關閉超時使用緩存
    cacheConfig.setUseCacheDataWhenUnexpired(true);  //開啓當緩存未過時時使用緩存
    cacheConfig.setRetryWhenRequestFailed(true); //開啓請求失敗重試
    cacheConfig.setNeverExpired(false); //關閉緩存永不過時

    TimeController timeController=new TimeController();
    timeController.setExpirationTime(DEFAULT_EXPIRATION_TIME); //設置緩存的過時時間
    timeController.setTimeout(DEFAULT_TIMEOUT); //設置緩存超時時間,對應「setUseCacheDataWhenTimeout」函數的超時時間
    cacheConfig.setTimeController(timeController); //把時間控制器設置給RequestCacheConfig

    return cacheConfig;
}

每次請求若是須要從新指定配置,本身構造這樣一個對象傳入便可

⑩原始發送請求方式

XRequest實際上是使用裝飾者模式,對一系列請求步驟進行了封裝,目的是爲了更簡單的使用,若是有複雜的需求,須要更高的自由度的話, 能夠參考以下發送請求代碼

MultipartGsonRequest<Bean> request = new MultipartGsonRequest<T>(cacheConfig, url, cacheKey, Bean.class, onRequestListener);
request.setRequestParams(params);
request.setHttpMethod(HttpMethod.POST);
request.setTag(tag);

XRequest.getInstance().addToRequestQueue(request);
相關文章
相關標籤/搜索