Android框架のOkhttp-com.zhousf.lib

OkHttp3

基于OkHttp3封裝的網(wǎng)絡(luò)請求庫

功能點(diǎn)

  • 支持Http/Https協(xié)議/自定義Https證書認(rèn)證
  • 支持同步/異步請求
  • 支持異步延遲執(zhí)行
  • 支持Post/Get/Put/Delete請求
  • 支持Cookie持久化,支持Gzip壓縮
  • 支持協(xié)議頭參數(shù)Head設(shè)置
  • 支持二進(jìn)制參數(shù)院仿、JSON磅废、表單提交、SOAP提交
  • 支持Gson解析飒炎、Unicode自動轉(zhuǎn)碼因妙、請求參數(shù)編碼以及服務(wù)器響應(yīng)編碼設(shè)置
  • 支持四種緩存類型請求:僅網(wǎng)絡(luò)荐操、僅緩存诅妹、先網(wǎng)絡(luò)再緩存罚勾、先緩存再網(wǎng)絡(luò)
  • 支持自定義緩存存活時(shí)間與緩存清理功能
  • 當(dāng)Activity/Fragment銷毀時(shí)自動取消相應(yīng)的所有網(wǎng)絡(luò)請求,支持取消指定請求
  • 異步請求響應(yīng)自動切換到UI線程吭狡,摒棄runOnUiThread
  • Application中自定義全局配置/增加系統(tǒng)默認(rèn)配置
  • 支持文件和圖片上傳/批量上傳尖殃,支持同步/異步上傳,支持進(jìn)度提示
  • 支持文件下載/批量下載赵刑,支持同步/異步下載,支持進(jìn)度提示
  • 支持文件斷點(diǎn)下載场刑,獨(dú)立下載的模塊摒棄了數(shù)據(jù)庫記錄斷點(diǎn)的過時(shí)方法
  • 完整的日志跟蹤與異常處理
  • 支持請求結(jié)果攔截以及異常處理攔截
  • 支持單例客戶端般此,提高網(wǎng)絡(luò)請求速率
  • 完整的API示例
  • 后續(xù)優(yōu)化中...

相關(guān)截圖

網(wǎng)絡(luò)請求演示

1.gif

先網(wǎng)絡(luò)再緩存演示

1.jpg

先緩存再網(wǎng)絡(luò)演示

2.gif

上傳圖片界面

3.gif

斷點(diǎn)下載文件界面

3.jpg

日志

2.jpg
  • GET-URL/POST-URL:請求地址
  • CostTime:請求耗時(shí)(單位:秒)
  • Response:響應(yīng)串

項(xiàng)目演示DEMO

項(xiàng)目中已包含所有支持業(yè)務(wù)的demo蚪战,詳情請下載項(xiàng)目參考源碼。

引用方式

Gradle

compile 'com.zhousf.lib:okhttp3:2.9.6'

compile project(':okhttp3')

若項(xiàng)目已包含support-annotations或出現(xiàn)support-annotations版本沖突請采用下面方式進(jìn)行依賴:

compile ('com.zhousf.lib:okhttp3:2.9.6'){
    exclude(module: 'support-annotations')
}

若項(xiàng)目已包含Gson或出現(xiàn)Gson版本沖突請采用下面方式進(jìn)行依賴:

compile ('com.zhousf.lib:okhttp3:2.9.6'){
    exclude(module:'gson')
}

ProGuard

如果你使用了ProGuard混淆铐懊,請?zhí)砑尤缦屡渲?

-dontwarn okio.**

權(quán)限

    <!-- 添加讀寫權(quán)限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <!-- 訪問互聯(lián)網(wǎng)權(quán)限 -->
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

自定義全局配置

在Application中配置如下:

        String downloadFileDir = Environment.getExternalStorageDirectory().getPath()+"/okHttp_download/";
        String cacheDir = Environment.getExternalStorageDirectory().getPath()+"/okHttp_cache";
        OkHttpUtil.init(context)
                .setConnectTimeout(15)//連接超時(shí)時(shí)間
                .setWriteTimeout(15)//寫超時(shí)時(shí)間
                .setReadTimeout(15)//讀超時(shí)時(shí)間
                .setMaxCacheSize(10 * 1024 * 1024)//緩存空間大小
                .setCacheType(CacheType.FORCE_NETWORK)//緩存類型
                .setHttpLogTAG("HttpLog")//設(shè)置請求日志標(biāo)識
                .setIsGzip(false)//Gzip壓縮邀桑,需要服務(wù)端支持
                .setShowHttpLog(true)//顯示請求日志
                .setShowLifecycleLog(false)//顯示Activity銷毀日志
                .setRetryOnConnectionFailure(false)//失敗后不自動重連
                .setCachedDir(new File(cacheDir))//設(shè)置緩存目錄
                .setDownloadFileDir(downloadFileDir)//文件下載保存目錄
                .setResponseEncoding(Encoding.UTF_8)//設(shè)置全局的服務(wù)器響應(yīng)編碼
                .setRequestEncoding(Encoding.UTF_8)//設(shè)置全局的請求參數(shù)編碼
                .setHttpsCertificate("12306.cer")//設(shè)置全局Https證書
                .addResultInterceptor(HttpInterceptor.ResultInterceptor)//請求結(jié)果攔截器
                .addExceptionInterceptor(HttpInterceptor.ExceptionInterceptor)//請求鏈路異常攔截器
                .setCookieJar(new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(context)))//持久化cookie
                .build();

獲取網(wǎng)絡(luò)請求客戶端單例示例

//獲取單例客戶端(默認(rèn))
 方法一、OkHttpUtil.getDefault(this)//綁定生命周期
            .doGetSync(HttpInfo.Builder().setUrl(url).build());
 方法二科乎、OkHttpUtil.getDefault()//不綁定生命周期
            .doGetSync(HttpInfo.Builder().setUrl(url).build());

取消指定請求

建議在視圖中采用OkHttpUtil.getDefault(this)的方式進(jìn)行請求綁定壁畸,該方式會在Activity/Fragment銷毀時(shí)自動取消當(dāng)前視圖下的所有請求; 請求標(biāo)識類型支持Object茅茂、String捏萍、Integer、Float空闲、Double令杈; 請求標(biāo)識務(wù)必保證唯一

//*******請求時(shí)先綁定請求標(biāo)識碴倾,根據(jù)該標(biāo)識進(jìn)行取消*******/
//方法一:
OkHttpUtil.Builder()
                .setReadTimeout(120)
                .build("請求標(biāo)識")//綁定請求標(biāo)識
                .doDownloadFileAsync(info);
//方法二:
OkHttpUtil.getDefault("請求標(biāo)識")//綁定請求標(biāo)識
            .doGetSync(info);

//*******取消指定請求*******/ 
OkHttpUtil.getDefault().cancelRequest("請求標(biāo)識");

HttpInfo參數(shù)解析:

  • 鍵值對提交采用addParam/addParams方法
  • Json提交采用addParamJson方法
  • 表單提交采用addParamForm方法
  • 二進(jìn)制字節(jié)流提交采用addParamBytes方法
  • 文件上傳采用addDownloadFile方法
  • 文件下載采用addUploadFile方法
HttpInfo.Builder()
        .setUrl(url)
        .setRequestType(RequestType.GET)//請求方式
        .addHead("head","test")//添加頭參數(shù)
        .setContentType(ContentType.SOAP)//設(shè)置媒體類型
        .addParam("param","test")//添加接口鍵值對參數(shù)
        .addParams(new HashMap<String, String>())//添加接口鍵值對參數(shù)集合
        .addParamBytes("byte")//添加二進(jìn)制流
        .addParamJson("json")//添加Json參數(shù)
        .addParamFile(new File(""))//添加文檔參數(shù)
        .addParamForm("form")//添加表單參數(shù)
        .addDownloadFile(new DownloadFileInfo("fileURL", "myMP4",null))//添加下載文件
        .addUploadFile("interfaceParamName","filePathWithName",null)//添加上傳文件
        .setResponseEncoding(Encoding.UTF_8)//設(shè)置服務(wù)器響應(yīng)編碼
        .setRequestEncoding(Encoding.UTF_8)//設(shè)置全局的請求參數(shù)編碼
        .setDelayExec(2, TimeUnit.SECONDS)//延遲2秒執(zhí)行
        .setHttpsCertificate("12306.cer")//設(shè)置Https證書
        .setNeedResponse(true)//設(shè)置返回結(jié)果為Response
        .build()

在Activity中同步調(diào)用示例

    /**
     * 同步請求:由于不能在UI線程中進(jìn)行網(wǎng)絡(luò)請求操作逗噩,所以采用子線程方式
     */
    private void sync() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                final HttpInfo info = HttpInfo.Builder()
                        .setUrl(url)
                        .setResponseEncoding(Encoding.UTF_8)//設(shè)置該接口的服務(wù)器響應(yīng)編碼
                        .setRequestEncoding(Encoding.UTF_8)//設(shè)置該接口的請求參數(shù)編碼
                        .build();
                OkHttpUtil.getDefault(this)
                        .doGetSync(info);
                final String result = info.getRetDetail();
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        resultTV.setText("同步請求:" + result);
                        setFromCacheTV(info);

                    }
                });
            }
        }).start();
    }

在Activity中異步調(diào)用示例

    /**
     * 異步請求:回調(diào)方法可以直接操作UI
     */
    private void async() {
        OkHttpUtil.getDefault(this).doGetAsync(
                HttpInfo.Builder().setUrl(url).build(),
                new Callback() {
                    @Override
                    public void onFailure(HttpInfo info) throws IOException {
                        String result = info.getRetDetail();
                        resultTV.setText("異步請求失敗:" + result);
                    }

                    @Override
                    public void onSuccess(HttpInfo info) throws IOException {
                        String result = info.getRetDetail();
                        resultTV.setText("異步請求成功:" + result);
                        //GSon解析
                        TimeAndDate time = info.getRetDetail(TimeAndDate.class);
                        LogUtil.d("MainActivity", time.getResult().toString());
                        setFromCacheTV(info);
                    }
                });
    }

僅網(wǎng)絡(luò)請求

    /**
     * 僅網(wǎng)絡(luò)請求
     */
    private void forceNetwork(){
        OkHttpUtil.Builder().setCacheType(CacheType.FORCE_NETWORK).build(this)
                .doGetAsync(
                        HttpInfo.Builder().setUrl(url).build(),
                        new Callback() {
                            @Override
                            public void onSuccess(HttpInfo info) throws IOException {
                                String result = info.getRetDetail();
                                resultTV.setText("FORCE_NETWORK:" + result);
                                setFromCacheTV(info);
                            }

                            @Override
                            public void onFailure(HttpInfo info) throws IOException {
                                resultTV.setText("FORCE_NETWORK:" + info.getRetDetail());
                            }
                        }
                );
    }

僅緩存請求

    /**
     * 僅緩存請求
     */
    private void forceCache(){
        OkHttpUtil.Builder().setCacheType(CacheType.FORCE_CACHE).build(this)
                .doGetAsync(
                        HttpInfo.Builder().setUrl(url).build(),
                        new Callback() {
                            @Override
                            public void onSuccess(HttpInfo info) throws IOException {
                                String result = info.getRetDetail();
                                resultTV.setText("FORCE_CACHE:" + result);
                                setFromCacheTV(info);
                            }

                            @Override
                            public void onFailure(HttpInfo info) throws IOException {
                                resultTV.setText("FORCE_CACHE:" + info.getRetDetail());
                            }
                        }
                );
    }

先網(wǎng)絡(luò)再緩存

    /**
     * 先網(wǎng)絡(luò)再緩存:先請求網(wǎng)絡(luò)跌榔,失敗則請求緩存
     */
    private void networkThenCache() {
        OkHttpUtil.Builder().setCacheType(CacheType.NETWORK_THEN_CACHE).build(this)
                .doGetAsync(
                        HttpInfo.Builder().setUrl(url).build(),
                        new Callback() {
                            @Override
                            public void onSuccess(HttpInfo info) throws IOException {
                                String result = info.getRetDetail();
                                resultTV.setText("NETWORK_THEN_CACHE:" + result);
                                setFromCacheTV(info);
                            }

                            @Override
                            public void onFailure(HttpInfo info) throws IOException {
                                resultTV.setText("NETWORK_THEN_CACHE:" + info.getRetDetail());
                            }
                        }
                );
    }

先緩存再網(wǎng)絡(luò)

    /**
     * 先緩存再網(wǎng)絡(luò):先請求緩存异雁,失敗則請求網(wǎng)絡(luò)
     */
    private void cacheThenNetwork() {
        OkHttpUtil.Builder().setCacheType(CacheType.CACHE_THEN_NETWORK).build(this)
                .doGetAsync(
                        HttpInfo.Builder().setUrl(url).build(),
                        new Callback() {
                            @Override
                            public void onSuccess(HttpInfo info) throws IOException {
                                String result = info.getRetDetail();
                                resultTV.setText("CACHE_THEN_NETWORK:" + result);
                                setFromCacheTV(info);
                            }

                            @Override
                            public void onFailure(HttpInfo info) throws IOException {
                                resultTV.setText("CACHE_THEN_NETWORK:" + info.getRetDetail());
                            }
                        }
                );
    }

緩存10秒失效

    /**
     * 緩存10秒失效:連續(xù)點(diǎn)擊進(jìn)行測試10秒內(nèi)再次請求為緩存響應(yīng),10秒后再請求則緩存失效并進(jìn)行網(wǎng)絡(luò)請求
     */
    private void tenSecondCache(){
        //由于采用同一個(gè)url測試僧须,需要先清理緩存
        if(isNeedDeleteCache){
            isNeedDeleteCache = false;
            OkHttpUtil.getDefault().deleteCache();
        }
        OkHttpUtil.Builder()
                .setCacheType(CacheType.CACHE_THEN_NETWORK)
                .setCacheSurvivalTime(10)//緩存存活時(shí)間為10秒
                .build(this)
                .doGetAsync(
                        HttpInfo.Builder().setUrl(url).build(),
                        new Callback() {
                            @Override
                            public void onSuccess(HttpInfo info) throws IOException {
                                String result = info.getRetDetail();
                                resultTV.setText("緩存10秒失效:" + result);
                                setFromCacheTV(info);
                            }

                            @Override
                            public void onFailure(HttpInfo info) throws IOException {
                                resultTV.setText("緩存10秒失效:" + info.getRetDetail());
                            }
                        }
                );
    }

在Activity中上傳圖片示例

 /**
     * 異步上傳圖片:顯示上傳進(jìn)度
     */
    private void doUploadImg() {
        HttpInfo info = HttpInfo.Builder()
                        .setUrl(url)
                        .addUploadFile("file", filePathOne, new ProgressCallback() {
                            //onProgressMain為UI線程回調(diào)纲刀,可以直接操作UI
                            @Override
                            public void onProgressMain(int percent, long bytesWritten, long contentLength, boolean done) {
                                uploadProgressOne.setProgress(percent);
                                LogUtil.d(TAG, "上傳進(jìn)度:" + percent);
                            }
                        })
                        .build();
        OkHttpUtil.getDefault(this).doUploadFileAsync(info);
    }

在Activity中單次批量上傳文件示例

  • 若服務(wù)器為php,接口文件參數(shù)名稱后面追加"[]"表示數(shù)組皆辽, 示例:builder.addUploadFile("uploadFile[]",path);
/**
     * 單次批量上傳:一次請求上傳多個(gè)文件
     */
     private void doUploadBatch(){
        imgList.clear();
        imgList.add("/storage/emulated/0/okHttp_download/test.apk");
        imgList.add("/storage/emulated/0/okHttp_download/test.rar");
        HttpInfo.Builder builder = HttpInfo.Builder()
                .setUrl(url);
        //循環(huán)添加上傳文件
        for (String path: imgList  ) {
            //若服務(wù)器為php柑蛇,接口文件參數(shù)名稱后面追加"[]"表示數(shù)組,示例:builder.addUploadFile("uploadFile[]",path);
            builder.addUploadFile("uploadFile",path);
        }
        HttpInfo info = builder.build();
        OkHttpUtil.getDefault(UploadFileActivity.this).doUploadFileAsync(info,new ProgressCallback(){
            @Override
            public void onProgressMain(int percent, long bytesWritten, long contentLength, boolean done) {
                uploadProgress.setProgress(percent);
            }

            @Override
            public void onResponseMain(String filePath, HttpInfo info) {
                LogUtil.d(TAG, "上傳結(jié)果:" + info.getRetDetail());
                tvResult.setText(info.getRetDetail());
            }
        });
    }

在Activity中斷點(diǎn)下載文件示例

 @OnClick({R.id.downloadBtn, R.id.pauseBtn, R.id.continueBtn})
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.downloadBtn://下載
                download();
                break;
            case R.id.pauseBtn://暫停下載
                if(null != fileInfo)
                    fileInfo.setDownloadStatus(DownloadStatus.PAUSE);
                break;
            case R.id.continueBtn://繼續(xù)下載
                download();
                break;
        }
    }

    private void download(){
        if(null == fileInfo)
            fileInfo = new DownloadFileInfo(url,"fileName",new ProgressCallback(){
                @Override
                public void onProgressMain(int percent, long bytesWritten, long contentLength, boolean done) {
                    downloadProgress.setProgress(percent);
                    tvResult.setText(percent+"%");
                    LogUtil.d(TAG, "下載進(jìn)度:" + percent);
                }
                @Override
                public void onResponseMain(String filePath, HttpInfo info) {
                    if(info.isSuccessful()){
                        tvResult.setText(info.getRetDetail()+"\n下載狀態(tài):"+fileInfo.getDownloadStatus());
                    }else{
                        Toast.makeText(DownloadBreakpointsActivity.this,info.getRetDetail(),Toast.LENGTH_SHORT).show();
                    }
                }
            });
        HttpInfo info = HttpInfo.Builder().addDownloadFile(fileInfo).build();
        OkHttpUtil.Builder().setReadTimeout(120).build(this).doDownloadFileAsync(info);
    }

二進(jìn)制流方式請求

HttpInfo info = new HttpInfo.Builder()
        .setUrl("http://192.168.120.154:8082/StanClaimProd-app/surveySubmit/getFileLen")
        .addParamBytes(byte)//添加二進(jìn)制流
        .build();
OkHttpUtil.getDefault().doPostAsync(info, new Callback() {
    @Override
    public void onSuccess(HttpInfo info) throws IOException {
        String result = info.getRetDetail();
        resultTV.setText("請求失斍啤:"+result);
    }

    @Override
    public void onFailure(HttpInfo info) throws IOException {
        resultTV.setText("請求成功:"+info.getRetDetail());
    }
});

請求結(jié)果統(tǒng)一預(yù)處理攔截器/請求鏈路異常信息攔截器示例

請求結(jié)果攔截器與鏈路異常攔截器方便項(xiàng)目進(jìn)行網(wǎng)絡(luò)請求業(yè)務(wù)時(shí)對信息返回的統(tǒng)一管理與設(shè)置

/**
 * Http攔截器
 * 1耻台、請求結(jié)果統(tǒng)一預(yù)處理攔截器
 * 2、請求鏈路異常信息攔截器
 * @author zhousf
 */
public class HttpInterceptor {

    /**
     * 請求結(jié)果統(tǒng)一預(yù)處理攔截器
     * 該攔截器會對所有網(wǎng)絡(luò)請求返回結(jié)果進(jìn)行預(yù)處理并修改
     */
    public static ResultInterceptor ResultInterceptor = new ResultInterceptor() {
        @Override
        public HttpInfo intercept(HttpInfo info) throws Exception {
            //請求結(jié)果預(yù)處理:可以進(jìn)行GSon過濾與解析
            return info;
        }
    };

    /**
     * 請求鏈路異常信息攔截器
     * 該攔截器會發(fā)送網(wǎng)絡(luò)請求時(shí)鏈路異常信息進(jìn)行攔截處理
     */
    public static ExceptionInterceptor ExceptionInterceptor = new ExceptionInterceptor() {
        @Override
        public HttpInfo intercept(HttpInfo info) throws Exception {
            switch (info.getRetCode()){
                case HttpInfo.NonNetwork:
                    info.setRetDetail("網(wǎng)絡(luò)中斷");
                    break;
                case HttpInfo.CheckURL:
                    info.setRetDetail("網(wǎng)絡(luò)地址錯(cuò)誤["+info.getNetCode()+"]");
                    break;
                case HttpInfo.ProtocolException:
                    info.setRetDetail("協(xié)議類型錯(cuò)誤["+info.getNetCode()+"]");
                    break;
                case HttpInfo.CheckNet:
                    info.setRetDetail("請檢查網(wǎng)絡(luò)連接是否正常["+info.getNetCode()+"]");
                    break;
                case HttpInfo.ConnectionTimeOut:
                    info.setRetDetail("連接超時(shí)");
                    break;
                case HttpInfo.WriteAndReadTimeOut:
                    info.setRetDetail("讀寫超時(shí)");
                    break;
                case HttpInfo.ConnectionInterruption:
                    info.setRetDetail("連接中斷");
                    break;
            }
            return info;
        }
    };
}

Cookie持久化示例

沒有在Application中進(jìn)行全局Cookie持久化配置時(shí)可以采用以下方式:

OkHttpUtilInterface okHttpUtil = OkHttpUtil.Builder()
            .setCacheLevel(FIRST_LEVEL)
            .setConnectTimeout(25).build(this);
//一個(gè)okHttpUtil即為一個(gè)網(wǎng)絡(luò)連接
okHttpUtil.doGetAsync(
                HttpInfo.Builder().setUrl(url).build(),
                new CallbackOk() {
                    @Override
                    public void onResponse(HttpInfo info) throws IOException {
                        if (info.isSuccessful()) {
                            String result = info.getRetDetail();
                            resultTV.setText("異步請求:"+result);
                        }
                    }
                });

相關(guān)示例

OkHttpUtil接口

/**
 * 網(wǎng)絡(luò)請求工具接口
 * @author zhousf
 */
public interface OkHttpUtilInterface {

    /**
     * 同步Post請求
     * @param info 請求信息體
     * @return HttpInfo
     */
    HttpInfo doPostSync(HttpInfo info);

    /**
     * 同步Post請求
     * @param info 請求信息體
     * @param callback 進(jìn)度回調(diào)接口
     * @return HttpInfo
     */
    HttpInfo doPostSync(HttpInfo info, ProgressCallback callback);

    /**
     * 異步Post請求
     * @param info 請求信息體
     * @param callback 結(jié)果回調(diào)接口
     */
    void doPostAsync(HttpInfo info, BaseCallback callback);

    /**
     * 異步Post請求
     * @param info 請求信息體
     * @param callback 進(jìn)度回調(diào)接口
     */
    void doPostAsync(HttpInfo info, ProgressCallback callback);

    /**
     * 同步Get請求
     * @param info 請求信息體
     */
    HttpInfo doGetSync(HttpInfo info);

    /**
     * 異步Get請求
     * @param info 請求信息體
     * @param callback 結(jié)果回調(diào)接口
     */
    void doGetAsync(HttpInfo info, BaseCallback callback);

    /**
     * 異步上傳文件
     * @param info 請求信息體
     */
    void doUploadFileAsync(final HttpInfo info);

    /**
     * 批量異步上傳文件
     * @param info 請求信息體
     * @param callback 進(jìn)度回調(diào)接口
     */
    void doUploadFileAsync(final HttpInfo info, ProgressCallback callback);

    /**
     * 同步上傳文件
     * @param info 請求信息體
     */
    void doUploadFileSync(final HttpInfo info);

    /**
     * 批量同步上傳文件
     * @param info 請求信息體
     * @param callback 進(jìn)度回調(diào)接口
     */
    void doUploadFileSync(final HttpInfo info, ProgressCallback callback);

    /**
     * 異步下載文件
     * @param info 請求信息體
     */
    void doDownloadFileAsync(final HttpInfo info);

    /**
     * 同步下載文件
     * @param info 請求信息體
     */
    void doDownloadFileSync(final HttpInfo info);

    /**
     * 同步Delete請求
     * @param info 請求信息體
     * @return HttpInfo
     */
    HttpInfo doDeleteSync(HttpInfo info);

    /**
     * 異步Delete請求
     * @param info 請求信息體
     * @param callback 結(jié)果回調(diào)接口
     */
    void doDeleteAsync(HttpInfo info, BaseCallback callback);

    /**
     * 同步Put請求
     * @param info 請求信息體
     * @return HttpInfo
     */
    HttpInfo doPutSync(HttpInfo info);

    /**
     * 異步PUT請求
     * @param info 請求信息體
     * @param callback 結(jié)果回調(diào)接口
     */
    void doPutAsync(HttpInfo info, BaseCallback callback);

    /**
     * 取消請求
     * @param requestTag 請求標(biāo)識
     */
    void cancelRequest(Object requestTag);

    /**
     * 獲取默認(rèn)的HttpClient
     */
    OkHttpClient getDefaultClient();

    /**
     * 清理緩存:只清理網(wǎng)絡(luò)請求的緩存空另,不清理下載文件
     */
    boolean deleteCache();

}

MainActivity

/**
 * 網(wǎng)絡(luò)請求:支持同步/異步盆耽、GET/POST、緩存請求
 *
 * @author zhousf
 */
public class MainActivity extends BaseActivity {

    @Bind(R.id.fromCacheTV)
    TextView fromCacheTV;
    @Bind(R.id.resultTV)
    TextView resultTV;
    /**
     * 注意:測試時(shí)請更換該地址
     */
    private String url = "http://api.k780.com:88/?app=life.time&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json";

    private boolean isNeedDeleteCache = true;

    @Override
    protected int initLayout() {
        return R.layout.activity_main;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    protected void onResume() {
        super.onResume();
    }

    @Override
    protected void onStart() {
        super.onStart();
    }

    @OnClick({
            R.id.sync_btn,
            R.id.async_btn,
            R.id.force_network_btn,
            R.id.force_cache_btn,
            R.id.network_then_cache_btn,
            R.id.cache_then_network_btn,
            R.id.ten_second_cache_btn,
            R.id.delete_cache_btn
    })
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.sync_btn://同步請求
                sync();
                break;
            case R.id.async_btn://異步請求
                async();
                break;
            case R.id.force_network_btn://僅網(wǎng)絡(luò)
                forceNetwork();
                break;
            case R.id.force_cache_btn://僅緩存
                forceCache();
                break;
            case R.id.network_then_cache_btn://先網(wǎng)絡(luò)再緩存
                networkThenCache();
                break;
            case R.id.cache_then_network_btn://先緩存再網(wǎng)絡(luò)
                cacheThenNetwork();
                break;
            case R.id.ten_second_cache_btn://緩存10秒失效
                tenSecondCache();
                break;
            case R.id.delete_cache_btn://清理緩存
                deleteCache();
                break;
        }
    }

    /**
     * 同步請求:由于不能在UI線程中進(jìn)行網(wǎng)絡(luò)請求操作扼菠,所以采用子線程方式
     */
    private void sync() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                final HttpInfo info = HttpInfo.Builder()
                        .setUrl(url)
                        .setResponseEncoding(Encoding.UTF_8)//設(shè)置服務(wù)器響應(yīng)編碼
                        .build();
                OkHttpUtil.getDefault(this)
                        .doGetSync(info);
                final String result = info.getRetDetail();
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        resultTV.setText("同步請求:" + result);
                        setFromCacheTV(info);

                    }
                });
            }
        }).start();
        needDeleteCache(true);
    }

    /**
     * 異步請求:回調(diào)方法可以直接操作UI
     */
    private void async() {
        OkHttpUtil.getDefault(this).doGetAsync(
                HttpInfo.Builder().setUrl(url).build(),
                new Callback() {
                    @Override
                    public void onFailure(HttpInfo info) throws IOException {
                        String result = info.getRetDetail();
                        resultTV.setText("異步請求失斏阍印:" + result);
                    }

                    @Override
                    public void onSuccess(HttpInfo info) throws IOException {
                        String result = info.getRetDetail();
                        resultTV.setText("異步請求成功:" + result);
                        //GSon解析
                        TimeAndDate time = new Gson().fromJson(result, TimeAndDate.class);
                        LogUtil.d("MainActivity", time.getResult().toString());
                        setFromCacheTV(info);
                    }
                });
        needDeleteCache(true);
    }

    /**
     * 僅網(wǎng)絡(luò)請求
     */
    private void forceNetwork(){
        OkHttpUtil.Builder().setCacheType(CacheType.FORCE_NETWORK).build(this)
                .doGetAsync(
                        HttpInfo.Builder().setUrl(url).build(),
                        new Callback() {
                            @Override
                            public void onSuccess(HttpInfo info) throws IOException {
                                String result = info.getRetDetail();
                                resultTV.setText("FORCE_NETWORK:" + result);
                                setFromCacheTV(info);
                            }

                            @Override
                            public void onFailure(HttpInfo info) throws IOException {
                                resultTV.setText("FORCE_NETWORK:" + info.getRetDetail());
                            }
                        }
                );
        needDeleteCache(true);
    }

    /**
     * 僅緩存請求
     */
    private void forceCache(){
        OkHttpUtil.Builder().setCacheType(CacheType.FORCE_CACHE).build(this)
                .doGetAsync(
                        HttpInfo.Builder().setUrl(url).build(),
                        new Callback() {
                            @Override
                            public void onSuccess(HttpInfo info) throws IOException {
                                String result = info.getRetDetail();
                                resultTV.setText("FORCE_CACHE:" + result);
                                setFromCacheTV(info);
                            }

                            @Override
                            public void onFailure(HttpInfo info) throws IOException {
                                resultTV.setText("FORCE_CACHE:" + info.getRetDetail());
                            }
                        }
                );
        needDeleteCache(true);
    }

    /**
     * 先網(wǎng)絡(luò)再緩存:先請求網(wǎng)絡(luò),失敗則請求緩存
     */
    private void networkThenCache() {
        OkHttpUtil.Builder().setCacheType(CacheType.NETWORK_THEN_CACHE).build(this)
                .doGetAsync(
                        HttpInfo.Builder().setUrl(url).build(),
                        new Callback() {
                            @Override
                            public void onSuccess(HttpInfo info) throws IOException {
                                String result = info.getRetDetail();
                                resultTV.setText("NETWORK_THEN_CACHE:" + result);
                                setFromCacheTV(info);
                            }

                            @Override
                            public void onFailure(HttpInfo info) throws IOException {
                                resultTV.setText("NETWORK_THEN_CACHE:" + info.getRetDetail());
                            }
                        }
                );
        needDeleteCache(true);
    }

    /**
     * 先緩存再網(wǎng)絡(luò):先請求緩存循榆,失敗則請求網(wǎng)絡(luò)
     */
    private void cacheThenNetwork() {
        OkHttpUtil.Builder().setCacheType(CacheType.CACHE_THEN_NETWORK).build(this)
                .doGetAsync(
                        HttpInfo.Builder().setUrl(url).build(),
                        new Callback() {
                            @Override
                            public void onSuccess(HttpInfo info) throws IOException {
                                String result = info.getRetDetail();
                                resultTV.setText("CACHE_THEN_NETWORK:" + result);
                                setFromCacheTV(info);
                            }

                            @Override
                            public void onFailure(HttpInfo info) throws IOException {
                                resultTV.setText("CACHE_THEN_NETWORK:" + info.getRetDetail());
                            }
                        }
                );
        needDeleteCache(true);
    }

    /**
     * 緩存10秒失效:連續(xù)點(diǎn)擊進(jìn)行測試10秒內(nèi)再次請求為緩存響應(yīng)析恢,10秒后再請求則緩存失效并進(jìn)行網(wǎng)絡(luò)請求
     */
    private void tenSecondCache(){
        //由于采用同一個(gè)url測試,需要先清理緩存
        if(isNeedDeleteCache){
            isNeedDeleteCache = false;
            OkHttpUtil.getDefault().deleteCache();
        }
        OkHttpUtil.Builder()
                .setCacheType(CacheType.CACHE_THEN_NETWORK)
                .setCacheSurvivalTime(10)//緩存存活時(shí)間為10秒
                .build(this)
                .doGetAsync(
                        HttpInfo.Builder().setUrl(url).build(),
                        new Callback() {
                            @Override
                            public void onSuccess(HttpInfo info) throws IOException {
                                String result = info.getRetDetail();
                                resultTV.setText("緩存10秒失效:" + result);
                                setFromCacheTV(info);
                            }

                            @Override
                            public void onFailure(HttpInfo info) throws IOException {
                                resultTV.setText("緩存10秒失效:" + info.getRetDetail());
                            }
                        }
                );
    }

    private void needDeleteCache(boolean delete){
        isNeedDeleteCache = delete;
    }

    private void setFromCacheTV(HttpInfo info){
        fromCacheTV.setText(info.isFromCache()?"緩存請求":"網(wǎng)絡(luò)請求");
    }

    /**
     * 清理緩存
     */
    private void deleteCache(){
        if(OkHttpUtil.getDefault().deleteCache()){
            ToastUtil.show(this,"清理緩存成功");
        }else{
            ToastUtil.show(this,"清理緩存失敗");
        }
    }

}

demo下載:藍(lán)奏云

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末秧饮,一起剝皮案震驚了整個(gè)濱河市映挂,隨后出現(xiàn)的幾起案子泽篮,更是在濱河造成了極大的恐慌,老刑警劉巖柑船,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件帽撑,死亡現(xiàn)場離奇詭異,居然都是意外死亡鞍时,警方通過查閱死者的電腦和手機(jī)亏拉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來逆巍,“玉大人及塘,你說我怎么就攤上這事≌粑” “怎么了磷蛹?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長溪烤。 經(jīng)常有香客問我味咳,道長,這世上最難降的妖魔是什么檬嘀? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任槽驶,我火速辦了婚禮,結(jié)果婚禮上鸳兽,老公的妹妹穿的比我還像新娘掂铐。我一直安慰自己,他們只是感情好揍异,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布全陨。 她就那樣靜靜地躺著,像睡著了一般衷掷。 火紅的嫁衣襯著肌膚如雪辱姨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天戚嗅,我揣著相機(jī)與錄音雨涛,去河邊找鬼。 笑死懦胞,一個(gè)胖子當(dāng)著我的面吹牛替久,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播躏尉,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蚯根,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了胀糜?” 一聲冷哼從身側(cè)響起颅拦,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤吼具,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后矩距,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡怖竭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年锥债,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了率寡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片比驻。...
    茶點(diǎn)故事閱讀 39,795評論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖很钓,靈堂內(nèi)的尸體忽然破棺而出广匙,到底是詐尸還是另有隱情允趟,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布鸦致,位于F島的核電站潮剪,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏分唾。R本人自食惡果不足惜抗碰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望绽乔。 院中可真熱鬧弧蝇,春花似錦、人聲如沸折砸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽睦授。三九已至两芳,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間睹逃,已是汗流浹背盗扇。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留沉填,地道東北人疗隶。 一個(gè)月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像翼闹,于是被迫代替她去往敵國和親斑鼻。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容