編輯:關於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(); } }
前言安卓開發中,在寫布局代碼的時候,ide可以看到布局的預覽效果。但是有些效果則必須在運行之後才能看見,比如這種情況:TextView在xml中沒有設置任何字符,而是在a
對Android 利用ViewPager實現圖片可以左右循環滑動效果,感興趣的朋友可以直接點擊查看內容詳情。主要介紹如何實現ViewPager自動播放,循環滾動的效果及使
AsyncTask,是android提供的輕量級的異步類,可以直接繼承AsyncTask,在類中實現異步操作,並提供接口反饋當前異步執行的程度(可以通過接口實現UI進度更
ListView是android中最常用的控件之一。 在實際運用中往往會遇到一次性加載全部數據過多,需要分頁加載增加程序運行效率! 本demo是將更新的監聽放在listv