okhttp緩存設置
⑴ okhttp3封裝工具類怎麼刪除緩存
系統數據類——系統文件存儲相關文件夾1、.android_secure:官方app2sd的產物,存儲了相關的軟體使用認證驗證,刪除之後SD卡中的軟體將無法使用。2、Android:存放重要的程序數據,比如google:map的地圖緩存,誤刪掉後地圖還需重新下載。3、backups:包含重要的備份文件,比如聯系人導出到SD卡會導入到此文件夾。4、bugtogo:系統出現問題的時候會形成一些報告文件,存放在此文件夾。5、data:緩存數據文件夾,與Android類似。例如,「截圖助手」截圖保存在data\com.edwardkim.android.screenshotitfull\screenshots里。6、LOST.DIR:卡上丟失或出錯的文件會移動到這里,此目錄刪了會自動生成。7、SystemAppBackup:SystemAppremove(深度卸載)備份系統文件後,備份文件保存的目錄。8、bugreports:升級系統或刷機,系統和程序發生兼容錯誤報告列表(包括內存使用全部內容)將保存在這個文件,重起機器可以刪除。9、.keepsafe:隱藏類的軟體、加密保存文件地址存放於此。10、.thumbs:瀏覽或使用某一軟體,以及使用某一文件夾後用於記錄次數和內容的文件,隨機產生,需要定期不斷清除,長時間不清理會大量佔用儲存卡的有效空間。11、openfeint:打開聯接網路後的一個啟動程序,它廣泛植入移動類平台發布的軟體或游戲,是更新下載或評論反饋信息的記錄地址,可刪除。12、com:播放類軟體在收看播放影視節目生成的文件將存放於此,可以對製作方反映回饋信息,可以刪除。13、Download(download):大寫字母的是網路聯接下載文件目錄,小寫字母的是手機自身(藍牙,近場等)存放下載傳輸文件,不要誤刪。系統工具類——系統自帶工具相關文件夾1、albumart:音樂專輯封面的緩存文件夾。2、albums:相冊縮略圖的緩存文件夾。3、cmp:音樂的緩存文件夾。4、Playlists:播放列表的緩存文件夾。5、DCIM:相機隨機緩存文件夾,記錄功能設置的參數,需要及時清理。一些第三方相機軟體拍出的相片也會保存在這里,比如360或暈影相機等。6、VPN:VPN數據的緩存目錄。7、Mydocuments:手機啟用各種程序任務記錄的文檔,需要定期清除,長時間不清理會佔用SD卡較大內存。8、.nomedia:手機中隱藏的音頻、圖片文件夾都會在這里顯示,可以自設在相關文件夾中。9、media:使用電話通話錄音軟體或在線瀏覽視頻等媒體產生的音頻文件記錄存檔將保存在此。10、.medieval_software:啟用藍牙傳輸軟體時,記錄任務保存文件的目錄。11、extracted:解壓縮軟體默認的解壓目錄。三方應用類1、.mobo:Moboplayer的緩存文件。2、.QQ:QQ的緩存文件,需要定期清除。3、.quickoffice:quickoffice的緩存文件。4、.switchpro:switchprowidget(多鍵開關應用)的緩存文件。5、.ucdlres:UC迅雷的緩存文件。6、:掌上網路、網路輸入法之類程序的緩存文件夾。7、etouch:易行的緩存文件夾。8、documents:DocumentsToGo的相關文件夾。9、gameloft:gameloft游戲數據包存放的文件夾。10、handcent:handcent(超級簡訊)數據文件夾。11、handyCurrency:貨幣匯率相關的文件夾,裝了handycalc(科學計算器)之後才會有。12、ireader:ireader的緩存文件夾。13、KingReader:開卷有益的緩存文件夾:下載的文件和應用都在這兒:刪除時留意看清14、LazyList:Applanet的緩存目錄,慎重使用。15、moji:墨跡天氣的緩存目錄。16、MusicFolders:poweramp產生的緩存文件夾。17、openfeint:openfeint的緩存文件夾。18、Picstore:圖片瀏覽軟體建立的一個目錄。19、renren:人人網客戶端的緩存文件夾。20、screenshot:截屏圖片保存的目錄。21、ShootMe:shootme截屏後圖片文件保存的目錄。22、SmartpixGames:SmartpixGames出品游戲的緩存文件夾,比如Jewellust。23、sogou:搜狗拼音輸入法的隨機緩存文件夾,可以刪除。24、SpeedSoftware:RE文件管理器的緩存文件夾。25、TalkingFriends:talkingtom(會說話的tom貓)錄制的視頻文件所保存的目錄。26、Tencent:騰訊軟體的緩存目錄,比如QQ。(與上面的.QQ文件夾並不相同)27、TitaniumBackup:鈦備份備份的程序所保存的目錄。28、TunnyBrowser:感覺是海豚瀏覽器的緩存目錄,但為什麼叫這個名字?金槍魚瀏覽器。.29、UCDLFiles:UC迅雷下載文件的保存目錄。30、UCDownloads:UC瀏覽器下載文件緩存的保存目錄。31、VIE:Vignette(暈影相機)的緩存目錄。32、yd_historys:有道詞典搜索歷史的緩存目錄33、yd_speech:有道詞典單詞發音的緩存目錄。34、youmicache:刪掉後還會自動生成,悠米廣告的緩存目錄,廣告程序內嵌在其程序中。35、Glu:Glu系列游戲的資料包存放地,如3D獵鹿人,勇猛二兄弟等。36、apadqq-images:QQforpad的緩存目錄。37、DunDef:地牢守護者的數據包。38、KuwoMusic:酷我音樂的相關文件夾。39、MxBrowser:遨遊的緩存目錄。40、Camera360:相機camera360的隨機緩存目錄,可以定期清除。41、TTPod:天天動聽的緩存目錄。42、downloaded:刷了MIUI,升級後的ZIP刷機包,保存在downloaded_rom里。43、.estrongs:當你使用了ES文件管理器解壓文件,會有這個緩存記錄。它反映使用進程,可以刪除。44、silentR:用了後台錄音軟體,自生的音頻文件夾,子文件夾phoneCalls,定期管理清除45、3D-compass:這是使用實景指南針軟體,生成的景象圖片(圖像和數字比較詳細)文件夾,可以清除。46、PDF:可移植文檔格式,Pdf閱讀器存儲文件夾。47、Zidanyou:是字典的詞庫文件儲存,刪除了要重新下載詞庫。48、Callrecords:採用第三方強制雙向錄音軟體(手機未root),音頻文件保存。49、VPlayerPro:是MOBO等視頻播放器使用後的記錄定期刪除。50、BeWeather(Videos):是氣象類軟體(如黑莓天氣.。.等)附加下載音頻或動畫圖標的儲存地址,刪除了會無圖無聲顯示。51、thumbnails:用第三方播放器觀看手持移動類視頻媒體時,存放點擊暫停、隨機截圖以及文件儲存時產生的內容。52、iQuran(meta2):可蘭經瀏覽文本和音頻的儲存文件。53、Autodesk:手機系統自帶存儲器命令生成文件夾:儲存圖像或編寫文稿,可以查看、備份或者刪除。54、PixlrOMatic:後期特效處理圖片軟體Pixlo,儲存文件夾,打開可以預覽看效果。55、mapbar:圖吧導航地圖存放文件,有必須主文件和不同地區具體地圖,主文件刪掉要重下!56、antTTS:是使用了高德導航選擇語音種類導航、語種的下載地址,刪掉了語音提示會丟失。57、kingsoft:金山詞霸專用文件夾下載儲存詞庫、更新拓展文匯(官方發布修正補充)。58、NightVisionCamera:夜間拍照相機相片存放的地址。59、DSA:電子狗專用夾,收錄各地區道路探頭監控位置信息,會定期更新。已測試配合高德、凱立德提前預警,效果不錯。60、apexlauncher:尖端桌面啟動器文件夾,位置在andriod/data/,放置桌面設置備份bak文件。
⑵ android okhttp怎麼刪除緩存
okhttp在3.0之後緩存時間很短,十幾秒,只有設置lurcache時才可以長時間緩存,清除緩存可以將lrucache清除
⑶ Android網路實戰篇——OkHttp3(Retrofit2)五種緩存模式的實現
網上有許多寫或搏OKhttp3緩存的文章,例如:
【Okhttp3結合Retrofit2 實現緩存】 https://www.jianshu.com/p/74d2c10c3eba?from=timeline
【使用衫侍祥Retrofit和Okhttp3實現網路緩存】談拆 https://www.jianshu.com/p/34f73e571ecb
【okhttp3緩存實踐】 http://blog.csdn.net/wuhengde/article/details/54927096
這些文章都很不錯,但還是有一些小小的瑕疵,這里我參考他們的文章結合自己的實踐簡單封裝了Okhttp3的五種緩存方式供大家參考,如有錯誤還請不吝賜教。
主要知識點:
public class OkHttpUtil {
}
後記:如有不同見解或疑惑,歡迎留言,如果覺得不錯可以來個贊!點個贊!
⑷ OkHttp的使用總結
dependencies{
//...
//OkHttp
implementation'com.squareup.okhttp3:okhttp:3.14.2'
implementation'com.squareup.okio:okio:1.17.4'
}
需要注意OkHttp在3.13.x以上的版本需要在Android 5.0+和java1.8的環境開發。Okio在1.x版本是基於Java實現的,2.x則是Kotlin實現的。
OkHttpClient:客戶端對象
Request:訪問請求,Post請求中需要包含RequestBody
RequestBody:請求數據,在Post請求中用到
Response:網路請求的響應結果
Interceptor:攔截器,能夠監控,重寫以及重試(請求的)調用
MediaType:數據類型,用來表明數據是json,image,pdf等一系列格式
client.newCall(request).execute():同步的請求方法。
client.newCall(request).enqueue(Callback callback):非同步的請求方法
注意點:Callback是執行在子線程中的,不能在此更新UI操作,okhttp2.2以後才有攔截器的概念。
1.同步get:需要自己寫子線程請求
2.非同步get
說明:Request.Builder 中默認使用get請求,所以可以不調用get()方法
3.post請求
其中RequestBody可以是JSON,表單,鍵值對,文件等
表單
基本流程都是先創建一個OkHttpClient對象,然後通過Request.Builder()創建一個Request對象,OkHttpClient對象調用newCall()並傳入Request對象就能Call對象。而同步和非同步不同的地方在於execute()和enqueue()方法的調用,調用execute()為同步請求並返回Response對象,調用enqueue()方法通過callback的形式返回Response對象。
其中這兩個方法最終會調用RealCall總的
()方法,從攔截器鏈中獲取返回結果;攔截器鏈中,依次通過RetryAndFollowUpInterceptor、BridgeInterceptor、CacheInterceptor、ConnectInterceptor、CallServerInterceptor,與伺服器建立連接後,獲取返回數據,在經過上述攔截器依次處理後,最後將結果返回給調用方。
攔截器的作用:可以在應用拿到response之前,先獲得response,對其某些數據進行監控,在有必要的情況下,對response中某些內容比如response的header,body,response內的request的header,body進行更改。
重拾及重定向攔截器RetryAndFollowUpInterceptor: 負責請求的重試和重定向
橋接攔截器BridgeInterceptor:給請求添加對用的header信息,處理響應結果的header信息
緩存攔截器CacheInterceptor:根據當前獲取的狀態選擇網路請求、讀取緩存、更新緩存。
連接攔截器ConnectInterceptor:建立http連接。
讀寫攔截器CallServerInterceptor:通過連接好的通道進行數據的交換;
1)ApplicationInterceptor(應用攔截器)
2)NetworkInterceptor(網路攔截器)
應用攔截器作用於okhttpCore和Application之間,網路攔截器作用於network和okhttpCore之間,添加應用攔截器的介面是addInterceptor(),而添加網路攔截器的介面是addNetworkInterceptor();
NetworkInterceptor:記錄日誌
ApplicationInterceptor:動態添加請求公共參數,檢查請求路徑許可權(如是否登錄狀態)
說明:在某些特殊情況下,網路攔截器可能被執行多次,但是applicationInterceptor只會被執行一次。
addHeader(String name, String value) :添加header信息
removeHeader(String name):移除header信息
header(String name, String value):重新設置指定name的header信息
headers(Headers headers):移除原有的header信息,將參數headers添加到請求中
⑸ okhttp3怎麼設置代理
okhttp3 復用okhttpclient配置
所有HTTP請求的代理設置,超時,緩存設置等都需要在OkHttpClient中設置。如果需要更改一個請求的配置,可以使用OkHttpClient.newBuilder()獲取一個builder對象,該builder對象與原來OkHttpClient共享相同的連接池,配置等。
如下示例,拷貝2個'OkHttpClient的配置,然後分別設置不同的超時時間;
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
Request request = new Request.Builder()
.url("http://httpbin.org/delay/1") // This URL is served with a 1 second delay.
.build();
try {
// Copy to customize OkHttp for this request.
OkHttpClient = client.newBuilder()
.readTimeout(500, TimeUnit.MILLISECONDS)
.build();
Response response = .newCall(request).execute();
System.out.println("Response 1 succeeded: " + response);
} catch (IOException e) {
System.out.println("Response 1 failed: " + e);
}
try {
// Copy to customize OkHttp for this request.
OkHttpClient = client.newBuilder()
.readTimeout(3000, TimeUnit.MILLISECONDS)
.build();
Response response = .newCall(request).execute();
System.out.println("Response 2 succeeded: " + response);
} catch (IOException e) {
System.out.println("Response 2 failed: " + e);
}
}
⑹ 如何用okhttp訪問本地url
POST TO A SERVER
Posting a String:
public static final MediaType jsonReq
= MediaType.parse(application/json; charset=utf-8);
OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
RequestBody body = RequestBody.create(jsonReq, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
Posting Streaming:
public static final MediaType MEDIA_TYPE_MARKDOWN
= MediaType.parse(text/x-markdown; charset=utf-8);
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
RequestBody requestBody = new RequestBody() {
@Override public MediaType contentType() {
return MEDIA_TYPE_MARKDOWN;
}
@Override public void writeTo(BufferedSink sink) throws IOException {
sink.writeUtf8(Numbers
);
sink.writeUtf8(-------
);
for (int i = 2; i <= 997; i++) {
sink.writeUtf8(String.format( * %s = %s
, i, factor(i)));
}
}
private String factor(int n) {
for (int i = 2; i < n; i++) {
int x = n / i;
if (x * i == n) return factor(x) + × + i;
}
return Integer.toString(n);
}
};
Request request = new Request.Builder()
.url()
.post(requestBody)
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException(Unexpected code + response);
System.out.println(response.body().string());
}
Posting a File:
public static final MediaType MEDIA_TYPE_MARKDOWN
= MediaType.parse(text/x-markdown; charset=utf-8);
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
File file = new File(README.md);
Request request = new Request.Builder()
.url()
.post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file))
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException(Unexpected code + response);
System.out.println(response.body().string());
}
Posting from parameters:
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
RequestBody formBody = new FormEncodingBuilder()
.add(search, Jurassic Park)
.build();
Request request = new Request.Builder()
.url()
.post(formBody)
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException(Unexpected code + response);
System.out.println(response.body().string());
}
Posting a multipart request:
private static final String IMGUR_CLIENT_ID = ...;
private static final MediaType MEDIA_TYPE_PNG = MediaType.parse(image/png);
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
// Use the imgur image upload API as documented at
RequestBody requestBody = new MultipartBuilder()
.type(MultipartBuilder.FORM)
.addPart(
Headers.of(Content-Disposition, form-data; name= itle),
RequestBody.create(null, Square Logo))
.addPart(
Headers.of(Content-Disposition, form-data; name=image),
RequestBody.create(MEDIA_TYPE_PNG, new File(website/static/logo-square.png)))
.build();
Request request = new Request.Builder()
.header(Authorization, Client-ID + IMGUR_CLIENT_ID)
.url()
.post(requestBody)
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException(Unexpected code + response);
System.out.println(response.body().string());
}
Posing Json with Gson
private final OkHttpClient client = new OkHttpClient();
private final Gson gson = new Gson();
public void run() throws Exception {
Request request = new Request.Builder()
.url()
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException(Unexpected code + response);
Gist gist = gson.fromJson(response.body().charStream(), Gist.class);
for (Map.Entry entry : gist.files.entrySet()) {
System.out.println(entry.getKey());
System.out.println(entry.getValue().content);
}
}
static class Gist {
Map files;
}
static class GistFile {
String content;
}
Response Caching:
為了緩存響應,你需要一個你可以讀寫的緩存目錄,和緩存大小的限制。這個緩存目錄應該是私有的,不信任的程序應不能讀取緩存內容。
一個緩存目錄同時擁有多個緩存訪問是錯誤的。大多數程序只需要調用一次 new OkHttp() ,在第一次調用時配置好緩存,然後其他地方只需要調用這個實例就可以了。否則兩個緩存示例互相干擾,破壞響應緩存,而且有可能會導致程序崩潰。
響應緩存使用HTTP頭作為配置。你可以在請求頭中添加 Cache-Control: max-stale=3600 ,OkHttp緩存會支持。你的服務通過響應頭確定響應緩存多長時間,例如使用 Cache-Control: max-age=9600 。
⑺ Okhttp 使用詳解
一個最簡單的OkHttpClient
一個復雜點的OkHttpClient配置
具體可配置參數見OkHttpClient.Builder類,幾點注意事項:
兩種攔截器的區別
官方提供的Logging Interceptor
地址: https://github.com/victorfan336/okhttp-logging-interceptor
gradle.build中添加依賴:
compile 'com.squareup.okhttp3:logging-interceptor:3.1.2'
通過Request.Builder創建請求,默認是Get請求
主要是構建RequestBody,並設置Content-Type消息頭洞擾。
1.普通Post請求
比如json請求
2. 使用FormBody傳遞鍵值對參數
Content-Type: application/x-www-form-urlencoded
比如:
3. 使用RequestBody傳遞Json或File對象
4. 使用MultipartBody同時傳遞鍵值對參數和File對象
5. 使用MultipartBody提交分塊請求
6. 自定義RequestBody實現流的上傳
1、同步執行
由於android強制要求網路請納段旦求在線程中執行,所以無法使用execute
2、非同步執行
1. 設置請求頭
2. 設置超時
3. 設置緩存
1、對於Get請求,如果請求參數較多,自己拼接Url較為麻煩
比如
拼接結果: http://www..com/user/login/username=zhangsan&password=123456
如果能做一燃褲些封裝,直接addParam(key,value)的形式則會簡單很多。
2、Callback在子線程中回調,大部分時候,我們都是需要更新UI的,還需自己post到主線程中處理。
3、構建請求步驟比較多
因此,Square提供了針對OkHttp的封裝庫Retrofit,另外Github上也有很多第三方的封裝庫,比如OkGo。
⑻ Okhttp解析(五)緩存的處理
大家好,之前我們講解了Okhttp網路數據請求相關的內容,這一節我們講講數據緩存的處理。本節按以下內容講解Okhttp緩存相關的內容。
緩存的使用場景很多,通過它可以將數據通過一定的規則存儲起來,再次請求數據的時候就可以快速從緩存中讀取了,緩存有以下優勢。
HTTP本身提供了一套緩存相關的機制。這套機制定義了相關的欄位和規則,用來客戶端和服務端進行緩存相關的協商,如響應的數據是否需要緩存,緩存有效期,緩存是否有效,伺服器端給出指示,而客戶端則根據服務端的指示做具體的緩存更新和讀取緩存工作。http緩存可以分為兩類:
強制緩存,在緩存數據未失效的情況下,可以直接使用緩存數據,有兩個欄位Expires和Cache-Control用於標明失效規則。
表示過期時間,由服務端返回。那麼下次請求數據時,判斷這個Expires過期時間是否已經過了,如果還沒有到過期時間,則使用緩存,如果過了過期時間,則重新請求伺服器的數據。Expires格式如下:
不過因為伺服器和客戶端的時間並不是同步的,用一個絕對時間作為過期的標記並不是很明智,所以HTTP1.1之後更多的是Cache-Control,它的控制更加靈活。
表示緩存的控制,有服務端返回。它有以下幾個取值:
默認情況下是private,也就是不能共享的。Cache-Control格式如下:
對比緩存,表示需要和服務端進行相關信息的對比,由伺服器決定是使用緩存還是最新內容,如果伺服器判定使用緩存,返回響應嗎304,判定使用最新內容,則返回響應碼200和最新數據。對比緩存的判定欄位有兩組:
ETag表示資源的一種標識信息,用於標識某個資源,由服務端返回,優先順序更高。格式如下:
然後客戶端再次請求時,加入欄位If-None-Match,格式如下:
服務端收到請求的該欄位時(之前的Etag值),和資源的唯一標識進行對比,如果相同,說明沒有改動,則返回狀態碼304,如果不同,說明資源被改過了,則返回狀態碼200和整個內容數據。
Last-Modified表示資源的最近修改時間,由服務端返回,優先順序更低。格式如下:
Last-Modified
由伺服器返回,表示響應的數據最近修改的時間。
If-Modified-Since
由客戶端請求,表示詢問伺服器這個時間是不是上次修改的時間。如果服務端該資源的修改時間小於等於If-Modified-Since指定的時間,說明資源沒有改動,返回響應狀態碼304,可以使用緩存。如果服務端該資源的修改時間大於If-Modified-Since指定的時間,說明資源又有改動了,則返回響應狀態碼200和最新數據給客戶端,客戶端使用響應返回的最新數據。
Last-Modified欄位的值(服務端返回的資源上次修改時間),常常被用於客戶端下次請求時的If-Modified-Since欄位中。
HTTP的緩存規則是優先考慮強制緩存,然後考慮對比緩存。
Okhttp緩存相關的類有如下:
要開啟使用Okhttp的緩存其實很簡單,只需要給OkHttpClient對象設置一個Cache對象即可,創建一個Cache時指定緩存保存的目錄和緩存最大的大小即可。
那麼下面我們來看看Okhttp緩存執行的大概流程
Okhttp的緩存流程分為讀取緩存和存儲緩存兩個過程,我們分別分析。
讀取使用緩存的流程從HttpEngine的sendRequest發送請求開始。
接下來我們分析
從Cache的get方法開始。它按以下步驟進行。
如果存在緩存的話,在指定的緩存目錄中,會有兩個文件「****.0」和「****.1」,分別存儲某個請求緩存的響應頭和響應體信息。(「****」是url的md5加密值)對應的ENTRY_METADATA響應頭和ENTRY_BODY響應體。緩存的讀取其實是由DiskLruCache來讀取的,DiskLruCache是支持Lru(最近最少訪問)規則的用於磁碟存儲的類,對應LruCache內存存儲。它在存儲的內容超過指定值之後,就會根據最近最少訪問的規則,把最近最少訪問的數據移除,以達到總大小不超過限制的目的。
接下來我們分析CacheStrategy緩存策略是怎麼判定的。
直接看CacheStrategy的get方法。緩存策略是由請求和緩存響應共同決定的。
接來下我們看看CacheControl類里有些什麼。
可以發現,它就是用於描述響應的緩存控制信息。
然後我們再看看Okhttp存儲緩存是怎麼進行的。
存儲緩存的流程從HttpEngine的readResponse發送請求開始的。
可以看到這里先通過maybeCache寫入了響應頭信息,再通過cacheWritingResponse寫入了響應體信息。我們再進去看Cache的put方法實現。
我們繼續看Cache的writeTo方法,可以看到是寫入一些響應頭信息。
到這里Okhttp緩存的讀取和存儲流程我們就清楚了。可以說,緩存的使用策略基本都是按照HTTP的緩存定義來實現的,所以對HTTP緩存相關欄位的理解是很重要的。然後關於DiskLruCache是如何管理緩存文件的,這個其實也很好理解,首先的原則就是按照LRU這種最近最少使用刪除的原則,當總的大小超過限定大小後,刪除最近最少使用的緩存文件,它的LRU演算法是使用LinkedHashMap進行維護的,這樣來保證,保留的緩存文件都是更常使用的。具體實現大家可以分析DiskLruCache和LinkedHashMap的實現原理。
⑼ 重識OkHttp——更深入了解如何使用
OkHttp作為square公司出品的一個網路請求框架,應該算是目前Android端最火爆的網路框架了。我公司目前的項目中採用的都是Rxjava結合Retrofit進行網路請求的處理,對於底層真正實現網路請求的OkHttp關注的不是很多。最近探究了一下OkHttp的源碼,對OkHttp的使用有了一些新的認識,在此做一下總結。
OkHttp作為當前Android端最火熱的網路請求框架,必然有很多的優點。
對於客戶端來講,我們關注的就是把正確的請求發送到服務端並拿到結果來進行處理。在OkHttp中,我認為可以分為3個部分:
OkHttp中通過建造者模式來構建OkHttpClient、Request和Response。對於客戶端來講,我們不需要過多關注Response是如何構建的,因為這個是OkHttp對響應結果進行了封裝處理。我們只關注請求Request和客戶端OkHttpClient如何構建即可。
Request採用建造者模式來配置url,請求方法method、header、tag和cacheControl。
OkHttp採用POST方法向伺服器發送一個請求體,在OkHttp中這個請求體是RequestBody。這個請求體可以是:
RequestBody有幾個靜態方法用於創建不同類型的請求體:
最終都是相當於重寫了RequestBody的兩個抽象方法來寫入流,如果傳遞流類型的參數,只要重寫這兩個抽象方法即可。
例如,我們提交一個String:
提交File:
提交流:
對於提交表單和分塊請求,OkHttp提供了兩個RequestBody的子類, FormBody 和 MultipartBody
FormBody也是採用建造者模式, 這個很簡單,添加key-value形式的鍵值對即可。
添加鍵值對有兩個方法:
例如:
MultipartBody也是採用建造者模式,MultipartBody.Builder可以構建兼容Html文件上傳表單的復雜請求體。每一部分的多塊請求體都是它自身的請求體,並且可以定義它自己的請求頭。如果存在的話,這些請求頭用來描述這部分的請求體。例如Content-Disposition、Content-Length 和 Content-Type如果可用就會被自動添加到頭。
MIME類型有:
有幾個主要的方法:
例如提交一個圖片文件:
OkHttpClient採用建造者模式,通過Builder可以配置連接超時時間、讀寫時間,是否緩存、是否重連,還可以設置各種攔截器interceptor等。
建議在一個App中,OkHttpClient保持一個實例。一個OkHttpClient支持一定數量的並發,請求同一個主機最大並發是5,所有的並發最大是64。這個與OkHttp中的調度器Dispatcher有關,可以設置並發數。本文不對Dispatcher進行討論。
一個例子:
OkHttpClient支持單獨配置,例如原來設置不同的請求時間,可以通過OkHttpClient的newBuilder()方法來重新構造一個OkHttpClient。例如:
上面已經講了如何創建Request和OkHttpClient,剩下的就是發送請求並得到伺服器的響應了。OkHttp發送請求可分為同步和非同步。OkHttpClient首先通過Request構建一個Call,通過這個Call去執行同步或者非同步請求。
同步方式,調用Call的execute()方法,返回Response,會阻塞當前線程:
非同步方式,調用Call的enqueue(CallBack callBack)方法,會在另一個線程中返回結果。
為了緩存響應,需要一個可讀寫並且設置大小Size的緩存目錄。緩存目錄需要私有,其它不信任的應用不能訪問這個文件。
如果同時有多個緩存訪問同一個緩存目錄會報錯。所以最好只在App中初始化一次OkHttpClient,給這個實例配置緩存,在整個App生命周期內都用這一個緩存。否則幾個緩存會相互影響,導致緩存出錯,引起程序崩潰。
響應緩存採用Http頭來配置,你可以添加這樣的請求頭 Cache-Control: max-stale=3600 。 max-age 指的是客戶端可以接收生存期不大於指定時間(以 秒 為單位)的響應。
為了防止響應使用緩存,可以用 CacheControl.FORCE_NETWORK 。為了防止使用網路,採用 CacheControl.FORCE_CACHE 。
調用Call.cancel()方法可以立即取消一個網路請求。如果當前線程正在寫request或者讀response會報IO異常。如果不再需要網路請求,採用這種方法是比較方便的。例如在App中返回了上一頁。無論是同步還是非同步的請求都可以被取消。
可以通過Response的code來判斷請求是否成功,如果伺服器返回的有數據,可以通過Response的body得到一個ResponseBody讀取。
如果採用ResponseBody的string()方法會一次性把數據讀取到內存中,如果數據超過1MB可能會報內存溢出,所以對於超過1MB的數據,建議採用流的方式去讀取,如ResponseBody的byteStream()方法。
需要說明的是:
OkHttp中的很多類都用到了建造者模式,可以根據需要靈活配置。採用建造者模式的有:
如果單獨使用OkHttp進行網路請求,通常需要開發者自己再封裝一下,如果不想重復造輪子,Github上面的有一些優秀開源庫可以拿來使用(本文只列出star較多的幾個):
OkHttp官方Wiki文檔