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,"清理緩存失敗");
}
}
}