編輯:關於Android編程
Okhttp是由Sqare公司開發的開源網絡訪問庫,是目前比較火的網絡框架, 它處理了很多網絡疑難雜症:會從很多常用的連接問題中自動恢復。如果你的服務器配置了多個IP地址,當第一個IP連接失敗的時候,OkHttp會自動嘗試下一個IP,此外OkHttp還處理了代理服務器問題和SSL握手失敗問題。
首先介紹下OkHttp的簡單使用,主要包含:
Eclipse的用戶,下載最新的okhttp jar包,導入工程。同時okhttp內部依賴okio,所以別忘了同時導入okio jar包。
添加網絡訪問權限
1.異步GET請求
最簡單的GET請求
private void getAsynHttp() {
OkHttpClient mOkHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url("http://www.baidu.com")
.build();
Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
showlog(e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
final String str = response.body().string();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplication(), str, Toast.LENGTH_SHORT).show();
}
});
}
});
}
基本的步驟很簡單,就是創建OkHttpClient、Request和Call,最後調用Call的enqueue()方法。但是每次這麼寫肯定是很麻煩,肯定是要進行封裝的。需要注意的是onResponse回調並不是在UI線程。
注:onResponse回調的參數是response,一般情況下,比如我們希望獲得返回的字符串,可以通過response.body().string()獲取;如果希望獲得返回的二進制字節數組,則調用response.body().bytes();如果你想拿到返回的inputStream,則調用response.body().byteStream()。
2.同步GET請求
同步Get請求和異步調用區別就是調用了call的execute()方法。
private String getSyncHttp() throws IOException{
OkHttpClient mOkHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url("http://www.baidu.com")
.build();
Call call = mOkHttpClient.newCall(request);
Response mResponse=call.execute();
if (mResponse.isSuccessful()) {
return mResponse.body().string();
} else {
throw new IOException("Unexpected code " + mResponse);
}
}
注意同步GET請求的調用必須放在子線程中執行,不然會報NetworkOnMainThreadException。
3.異步POST請求
post與get不同的就是要創建RequestBody並傳進Request中,同樣onResponse回調不是在UI線程。
private void postAsynHttp() {
OkHttpClient mOkHttpClient = new OkHttpClient();
RequestBody formBody = new FormBody.Builder()
.add("topicId", "1002")
.add("maxReply", "-1")
.add("reqApp", "1")
.build();
Request request = new Request.Builder()
.url("http://61.129.89.191/SoarAPI/api/SoarTopic")
.post(formBody)
.build();
Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
showlog(e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
final String str = response.body().string();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), str, Toast.LENGTH_SHORT).show();
}
});
}
});
}
1.異步上傳文件
上傳文件本身也是一個POST請求,首先定義上傳文件類型:
public final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8");
將sdcard根目錄的demo.txt文件上傳到服務器上:
private void postAsynFile() {
OkHttpClient mOkHttpClient=new OkHttpClient();
File file = new File("/sdcard/demo.txt");
Request request = new Request.Builder()
.url("https://api.github.com/markdown/raw")
.post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file))
.build();
mOkHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
showlog(e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
showlog(response.body().string());
}
});
}
當然如果想要改為同步的上傳文件只要調用 mOkHttpClient.newCall(request).execute()就可以了。
在demo.txt文件中有一行字“測試OkHttp異步上傳”我們運行程序點擊發送文件按鈕,最終請求網絡返回的結果就是我們txt文件中的內容 :

當然不要忘了添加如下權限:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwcmUgY2xhc3M9"brush:java;">
2.異步下載圖片
下載圖片本身也是一個GET請求
private void getAsynFile() {
OkHttpClient mOkHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url("http://img.my.csdn.net/uploads/201309/01/1378037128_5291.jpg")
.build();
Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
showlog(e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
final byte[] data = response.body().bytes();
runOnUiThread(new Runnable() {
@Override
public void run() {
Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, data.length);
image.setImageBitmap(bmp);
}
});
}
});
}
對於圖片下載,文件下載其實是類似的;圖片下載是通過回調的Response拿到byte[]然後decode成圖片;文件下載則是拿到inputStream做寫文件操作,我們這裡就不贅述了。
如果每次請求網絡都需要寫重復的代碼絕對是令人頭疼的,網上也有很多對OkHttp封裝的優秀開源項目,譬如OkHttpUtils,封裝的意義就在於更加方便的使用,具有拓展性,但是對OkHttp封裝最需要解決的是以下的兩點:
避免重復代碼調用 將請求結果回調改為UI線程根據以上兩點,我也做一個簡單的封裝,首先呢我們寫一個抽象類用於請求回調:
public interface ReqCallBack{ /**響應成功*/ void onReqSuccess(T result); /**響應失敗*/ void onReqFailed(String errorMsg); }
接下來創建一個OkHttpManager類封裝OkHttp,並實現了異步GET請求:
public class OkHttpManager {
private static volatile OkHttpManager mInstance;//單例引用
private OkHttpClient mOkHttpClient;//okHttpClient實例
private Handler okHttpHandler;//全局處理子線程和主線程通信
/**
* 初始化OkHttpManager
*/
public OkHttpManager(Context context) {
//初始化OkHttpClient
mOkHttpClient = new OkHttpClient().newBuilder()
.connectTimeout(10, TimeUnit.SECONDS)//設置超時時間
.readTimeout(10, TimeUnit.SECONDS)//設置讀取超時時間
.writeTimeout(10, TimeUnit.SECONDS)//設置寫入超時時間
.build();
//初始化Handler
okHttpHandler = new Handler(context.getMainLooper());
}
/**
* 獲取單例引用
*/
public static OkHttpManager getInstance(Context context) {
if (mInstance == null) {
synchronized (OkHttpManager.class) {
if (mInstance == null) {
mInstance = new OkHttpManager(context);
}
}
}
return mInstance;
}
/**
* okHttp get異步請求
* @param actionUrl 接口地址
* @param callBack 請求返回數據回調
* @param 數據泛型
* @return
*/
public Call getAsynHttp(String url, final ReqCallBack callBack) {
try {
final Request request = new Request.Builder()
.url(url)
.build();
Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
failedCallBack("訪問失敗", callBack);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
String string = response.body().string();
successCallBack((T) string, callBack);
} else {
failedCallBack("服務器錯誤", callBack);
}
}
});
return call;
} catch (Exception e) {}
return null;
}
/**
* 統一處理成功信息
* @param result
* @param callBack
* @param
*/
private void successCallBack(final T result, final ReqCallBack callBack) {
okHttpHandler.post(new Runnable() {
@Override
public void run() {
if (callBack != null) {
callBack.onReqSuccess(result);
}
}
});
}
/**
* 統一處理失敗信息
* @param errorMsg
* @param callBack
* @param
*/
private void failedCallBack(final String errorMsg, final ReqCallBack callBack) {
okHttpHandler.post(new Runnable() {
@Override
public void run() {
if (callBack != null) {
callBack.onReqFailed(errorMsg);
}
}
});
}
}
最後使用這個OkHttpManager來請求網絡:
OkHttpManager.getInstance(this).getAsynHttp("http://www.baidu.com", new ReqCallBack() {
@Override
public void onReqSuccess(String result) {
Toast.makeText(getApplicationContext(), result, Toast.LENGTH_SHORT).show();
}
@Override
public void onReqFailed(String errorMsg) {
showlog(errorMsg);
}
});
是不是很簡單呢?就幾句代碼就實現了GET請求,而且請求結果回調是在UI線程的。這裡只是一個很簡單的封裝例子,如果用在正式項目裡推薦OkHttpUtils。
一般情況下服務端默認返回的是Json字符串,上面通過封裝我們直接將Json返回給客戶端。其實封裝內部還能通過GSON解析讓客戶端直接獲取對象。
首先新建兩個Bean文件:
public class Weather {
public WeatherInfo weatherinfo;
}
public class WeatherInfo {
public String city;
public String cityid;
public String date_y;
public String temp1;
public String weather1;
public String toString() {
return "[city:"+city+" cityid:"+cityid+" date_y:"+date_y+" temp1:"+temp1+" weather1:"+weather1+"]";
}
}
改寫上面的OkHttpManager,在服務器端成功返回Json後做一次轉換,將Json字符串轉換成Weather對象:
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
String string = response.body().string();
Weather weather = new Gson().fromJson(string, Weather.class);
successCallBack((T) weather, callBack);
} else {
failedCallBack("服務器錯誤", callBack);
}
}
請求網絡,這裡泛型類型我們傳入Weather:
OkHttpManager.getInstance(this).getAsynHttp("http://weather.51wnl.com/weatherinfo/GetMoreWeather?cityCode=101020100&weatherType=0", new ReqCallBack() {
@Override
public void onReqSuccess(Weather weather) {
WeatherInfo weatherInfo = weather.weatherinfo;
showlog(weatherInfo.toString());
}
@Override
public void onReqFailed(String errorMsg) {
showlog(errorMsg);
}
});

可以看到,這裡返回的已經是Weather對象了。注意,在正式項目裡對OkHttp做封裝時要考慮全面,對傳進來的不同類型要生成不同的對象,而不僅僅是這裡的Weather。
使用緩存可以讓我們的app不用長時間地顯示令人厭煩的加載圈,提高了用戶體驗,而且還節省了流量,在數據更新不是很頻繁的地方使用緩存就非常有必要了。想要加入緩存不需要我們自己來實現,Okhttp已經內置了緩存,默認是不使用的,如果想使用緩存我們需要手動設置。
服務器支持緩存
如果服務器支持緩存,請求返回的Response會帶有這樣的Header:Cache-Control, max-age=xxx,這種情況下我們只需要手動給okhttp設置緩存就可以讓okhttp自動幫你緩存了。這裡的max-age的值代表了緩存在你本地存放的時間,可以根據實際需要來設置其大小。
首先我們要提供了一個文件路徑用來存放緩存,另外還需要指定緩存的大小就可以創建一個緩存了。
File sdcache = getExternalCacheDir(); int cacheSize = 10 * 1024 * 1024; Cache cache = new Cache(sdcache.getAbsoluteFile(), cacheSize);
創建了這個緩存後我們還需要將其設置到okttpClient對象裡面:
OkHttpClient mOkHttpClient = new OkHttpClient().newBuilder()
.cache(cache)
.connectTimeout(20, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
.build();
服務器不支持緩存
如果服務器不支持緩存就可能沒有指定這個頭部,或者指定的值是如no-store等,但是我們還想在本地使用緩存的話要怎麼辦呢?這種情況下我們就需要使用Interceptor來重寫Respose的頭部信息,從而讓okhttp支持緩存。
如下所示,我們重寫的Response的Cache-Control字段:
public class CacheInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
return response.newBuilder()
.removeHeader("Pragma")
.removeHeader("Cache-Control")
//cache for 30 days
.header("Cache-Control", "max-age=" + 3600 * 24 * 30)
.build();
}
}
然後將該Intercepter作為一個NetworkInterceptor加入到okhttpClient中:
OkHttpClient okHttpClient = new OkHttpClient();
OkHttpClient mOkHttpClient = okHttpClient.newBuilder()
.addNetworkInterceptor(new CacheInterceptor())
.cache(cache)
.connectTimeout(20, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
.build();
Request request = new Request.Builder()
.url("http://www.baidu.com")
.build();
Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {}
@Override
public void onResponse(Call call, final Response response) throws IOException {
if (null != response.cacheResponse()) {
String str = response.cacheResponse().toString();
showlog("cache--->" + str);
} else {
response.body().string();
String str=response.networkResponse().toString();
showlog("network--->" + str);
}
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "請求成功", Toast.LENGTH_SHORT).show();
}
});
}
});
這樣我們就可以在服務器不支持緩存的情況下使用緩存了。第一次請求會請求網絡得到數據,第二次以及後面的請求則會從緩存中取出數據:

當然也有種情況是有的請求每次都需要最新的數據,則在創建Request,來設置cacheControl為“CacheControl.FORCE_NETWORK”,用來表示請求會一直請求網絡得到數據:
final Request request = new Request.Builder()
.url("http://www.baidu.com")
.cacheControl(CacheControl.FORCE_NETWORK)
.build();

可以看到每次返回結果都來自網絡。
兩個CacheControl常量介紹:
CacheControl.FORCE_CACHE; //僅僅使用緩存 CacheControl.FORCE_NETWORK;//僅僅使用網絡
但是大家必須注意一點,okhttp的緩存設計和浏覽器的一樣,是用來提升用戶體驗降低服務器負荷的,比如:我們在有網的時候也會先調用緩存,但是有個時間限制,例如1分鐘之內,有網和沒有網都是先讀緩存,這個可以參考下面講解的第一種類型。
如果你想要做成那種離線可以緩存,在線就獲取最新數據的功能,可以參考第二種類型。
1、創建攔截器:
Interceptor interceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
String cacheControl = request.cacheControl().toString();
if (TextUtils.isEmpty(cacheControl)) {
cacheControl = "public, max-age=60";
}
return response.newBuilder()
.header("Cache-Control", cacheControl)
.removeHeader("Pragma")
.build();
}
};
設置max-age為60s之後,這60s之內不管你有沒有網,都讀緩存。如果cache沒有過期會直接返回cache而不會發起網絡請求,若過期會自動發起網絡請求。
2、設置client
/**創建OkHttpClient,並添加攔截器和緩存代碼**/
OkHttpClient client = new OkHttpClient.Builder()
.addNetworkInterceptor(interceptor)
.cache(cache).build();
第二種類型(離線可以緩存,在線就獲取最新數據)
這種方法和第一種方法的區別是在設置的攔截器上,這裡不能使用NetworkInterceptor,而是需要使用AppInterceptor。
先講一下步驟:
1、首先,給OkHttp設置攔截器
2、然後,在攔截器內做Request攔截操作,在每個請求發出前,判斷一下網絡狀況,如果沒問題繼續訪問,如果有問題,則設置從本地緩存中讀取
3、接下來是設置Response,先判斷網絡,網絡好的時候,移除header後添加cache失效時間為0小時,網絡未連接的情況下設置緩存時間為4周
代碼:
1、給OkHttp設置攔截器(用Interceptor)
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.cache(cache).build();
2、Request攔截操作
Request request = chain.request();
/**注意:如果您使用FORCE_CACHE和網絡的響應需求,OkHttp則會返回一個504提示,告訴你不可滿足請求響應。所以我們加一個判斷在沒有網絡的情況下使用*/
if (!isNetworkAvailable(MainActivity.this)) {
request = request.newBuilder()
.cacheControl(CacheControl.FORCE_CACHE) //無網絡時,強制從緩存取
.build();
showlog("no network");
}
3、設置Response
Response response = chain.proceed(request);
if (isNetworkAvailable(MainActivity.this)) {
int maxAge = 0 * 60; // 有網絡時,設置緩存超時時間0個小時
showlog("has network maxAge="+maxAge);
response.newBuilder()
.header("Cache-Control", "public, max-age=" + maxAge)
.removeHeader("Pragma")// 清除頭信息,因為服務器如果不支持,會返回一些干擾信息,不清除下面無法生效
.build();
} else {
showlog("network error");
int maxStale = 60 * 60 * 24 * 28; // 無網絡時,設置超時為4周
showlog("has maxStale="+maxStale);
response.newBuilder()
.header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
.removeHeader("Pragma")
.build();
showlog("response build maxStale="+maxStale);
}
return response;
查看緩存文件:
運行程序,在Android/data/com.hx.okhttp.cache下會發現很多緩存文件,這些緩存文件全是以url的md5加密字段為文件名,每一個response分兩個文件保存,以.0和.1結尾的文件區分。 進去看裡面的內容如下: .0的文件裡面是header,而.1文件裡面是返回的具體內容,即json數據。

分別看一下內容吧:

因為百度html頁面含有中文,這裡看到數據有亂碼現象

使用call.cancel()可以立即停止掉一個正在執行的call。如果一個線程正在寫請求或者讀響應,將會引發IOException。當用戶離開一個應用時或者跳到其他界面時,使用Call.cancel()可以節約網絡資源,另外不管同步還是異步的call都可以取消。
也可以通過tags來同時取消多個請求。當你構建一請求時,使用RequestBuilder.tag(tag)來分配一個標簽。之後你就可以用OkHttpClient.cancel(tag)來取消所有帶有這個tag的call。
為了模擬這個場景我們首先創建一個定時的線程池:
private ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
private void cancelCall(){
OkHttpClient mOkHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url("http://www.baidu.com")
.cacheControl(CacheControl.FORCE_NETWORK)
.build();
Call call = null;
call = mOkHttpClient.newCall(request);
final Call finalCall = call;
//100毫秒後取消call
executor.schedule(new Runnable() {
@Override
public void run() {
finalCall.cancel();
}
}, 100, TimeUnit.MILLISECONDS);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {}
@Override
public void onResponse(Call call,final Response response) {
if (null != response.cacheResponse()) {
String str = response.cacheResponse().toString();
showlog("cache--->" + str);
} else {
try {
response.body().string();
} catch (IOException e) {
showlog("IOException");
e.printStackTrace();
}
String str = response.networkResponse().toString();
showlog("network--->" + str);
}
}
});
showlog("是否取消成功"+call.isCanceled());
}
100毫秒後調用call.cancel(),為了能讓請求耗時,我們設置每次請求都要請求網絡,運行程序並且不斷的快速點擊發送請求按鈕:

很明顯每次cancel()都失敗了,仍舊成功的訪問了網絡。每隔100毫秒來調用call.cancel()顯然時間間隔太長,這段時間網絡已經返回了數據,我們設置為1毫秒並不斷的快速的點擊發送請求按鈕:

這次每次cancel()操作都成功了。

統一的文件下載管理(DownloadManager)
默認使用的是 get 請求,同時下載數量為3個,支持斷點下載,斷點信息使用ORMLite數據庫框架保存,默認下載路徑/storage/emulated/0/download,下載路徑和下載數量都可以在代碼中配置,下載管理使用了服務提高線程優先級,避免後台下載時被系統回收。
當你的項目需要做大量的下載的時候,並且多個頁面需要監聽下載進度,使用該擴展讓你更方便。原生支持下載任務的開始、暫停、停止、出錯、完成五個狀態,當同時下載任務數量超過3個(可代碼動態設置)時,後續任務自動等待,當有任務下載完成時,等待任務按照優先級自動開始下載。
統一的文件上傳管理(UploadManager)
默認使用的是 post 上傳請求,該上傳管理為簡單管理,不支持斷點續傳和分片上傳,只是簡單的將所有上傳任務使用線程池進行了統一管理,默認同時上傳數量為1個。由於斷點分片上傳的技術需要大量的服務端代碼配合,同時也會極大的增加客戶端代碼量,所以綜合考慮,該框架不做實現。如果確實有特殊需要,可以自己做擴展。
優勢一:性能高,專注於簡單易用的網絡請求,使用主流的okhttp進行封裝,對於okhttp大家都知道,在Android4.4的源碼中可以看到HttpURLConnection已經替換成OkHttp實現了,並且支持HTTP2/SPDY黑科技,支持socket自動選擇最好路線,並支持自動重連,擁有自動維護的socket連接池,減少握手次數,擁有隊列線程池,輕松寫並發。
優勢二:特有的網絡緩存模式,是大多數網絡框架所不具備的,說一個應用場景,老板說我們的app不僅需要在有網的情況下展示最新的網絡數據,還要在沒網的情況下使用緩存數據,這時候是不是項目中出現了大量的代碼判斷當前網絡狀況,根據不同的狀態保存不同的數據,然後決定是否使用緩存。細想一下,這是個通用的寫法,於是OkHttpUtils提供了四種緩存模式,讓你不用關心緩存的實現,而專注於數據的處理。
優勢三:方便易用的擴展接口,可以添加全局的公共參數,全局攔截器,全局超時時間,更可以對單個請求定制攔截器,超時時間,請求參數修改等等,在使用上更是方便,原生支持的鏈式調用讓你的請求更加清晰。
優勢四:強大的Cookie保持策略,我們知道在客戶端對cookie的獲取是個不太簡單的事情,特別是還要處理cookie的過期時間,持久化策略等等,OkHttpUtils幫你徹底解決Cookie的難題,默認擁有內存存儲和持久化存儲兩種實現,cookie全程自動管理,並且提供了額外的addCookie方式,允許介入到自動管理的過程中,添加你想創建的任何cookie。
Eclipse的用戶,導入JAR包或添加依賴工程:
見我後面的Demo,用得是依賴工程。
添加網絡訪問權限和讀寫SD卡權限:
一般在 Aplication,或者基類中,只需要調用一次即可,可以配置調試開關,全局的超時時間,公共的請求頭和請求參數等信息,所有的請求參數都支持中文。
@Override
public void onCreate() {
super.onCreate();
//---------這裡給出的是示例代碼,告訴你可以這麼傳,實際使用的時候,根據需要傳,不需要就不傳-------------//
HttpHeaders headers = new HttpHeaders();
headers.put("commonHeaderKey1", "commonHeaderValue1"); //header不支持中文
headers.put("commonHeaderKey2", "commonHeaderValue2");
HttpParams params = new HttpParams();
params.put("commonParamsKey1", "commonParamsValue1"); //param支持中文,直接傳,不要自己編碼
params.put("commonParamsKey2", "這裡支持中文參數");
//-----------------------------------------------------------------------------------//
//必須調用初始化
OkHttpUtils.init(this);
//以下設置的所有參數是全局參數,同樣的參數可以在請求的時候再設置一遍,那麼對於該請求來講,請求中的參數會覆蓋全局參數
//好處是全局參數統一,特定請求可以特別定制參數
try {
//以下都不是必須的,根據需要自行選擇,一般來說只需要 debug,緩存相關,cookie相關的 就可以了
OkHttpUtils.getInstance()
//打開該調試開關,控制台會使用 紅色error 級別打印log,並不是錯誤,是為了顯眼,不需要就不要加入該行
.debug("OkHttpUtils")
//如果使用默認的 60秒,以下三行也不需要傳
.setConnectTimeout(OkHttpUtils.DEFAULT_MILLISECONDS) //全局的連接超時時間
.setReadTimeOut(OkHttpUtils.DEFAULT_MILLISECONDS) //全局的讀取超時時間
.setWriteTimeOut(OkHttpUtils.DEFAULT_MILLISECONDS) //全局的寫入超時時間
//可以全局統一設置緩存模式,默認是不使用緩存,可以不傳
.setCacheMode(CacheMode.NO_CACHE)
//可以全局統一設置緩存時間,默認永不過期
.setCacheTime(CacheEntity.CACHE_NEVER_EXPIRE)
//如果不想讓框架管理cookie,以下不需要
// .setCookieStore(new MemoryCookieStore()) //cookie使用內存緩存(app退出後,cookie消失)
.setCookieStore(new PersistentCookieStore()) //cookie持久化存儲,如果cookie不過期,則一直有效
//可以設置https的證書,以下幾種方案根據需要自己設置
// .setCertificates() //方法一:信任所有證書(選一種即可)
// .setCertificates(getAssets().open("srca.cer")) //方法二:也可以自己設置https證書(選一種即可)
// .setCertificates(getAssets().open("aaaa.bks"), "123456", getAssets().open("srca.cer"))//方法三:傳入bks證書,密碼,和cer證書,支持雙向加密
//可以添加全局攔截器,不會用的千萬不要傳,錯誤寫法直接導致任何回調不執行
// .addInterceptor(new Interceptor() {
// @Override
// public Response intercept(Chain chain) throws IOException {
// return chain.proceed(chain.request());
// }
// })
//這兩行同上,不需要就不要傳
.addCommonHeaders(headers) //設置全局公共頭
.addCommonParams(params); //設置全局公共參數
} catch (Exception e) {
e.printStackTrace();
}
}
深入理解Android中的xmlns:tools屬性
前言安卓開發中,在寫布局代碼的時候,ide可以看到布局的預覽效果。但是有些效果則必須在運行之後才能看見,比如這種情況:TextView在xml中沒有設置任何字符,而是在a
Android 使用ViewPager自動滾動循環輪播效果
對Android 利用ViewPager實現圖片可以左右循環滑動效果,感興趣的朋友可以直接點擊查看內容詳情。主要介紹如何實現ViewPager自動播放,循環滾動的效果及使
Android利用異步任務AsyncTask發送post請求獲取json數據
AsyncTask,是android提供的輕量級的異步類,可以直接繼承AsyncTask,在類中實現異步操作,並提供接口反饋當前異步執行的程度(可以通過接口實現UI進度更
ListView 分頁加載更新實例分享
ListView是android中最常用的控件之一。 在實際運用中往往會遇到一次性加載全部數據過多,需要分頁加載增加程序運行效率! 本demo是將更新的監聽放在listv