安卓高階 8 之Okhttp3 10快取層原理分析

2021-08-29 04:02:09 字數 4776 閱讀 5368

用乙個demo展示okhttp如何對介面資料進行快取;

講解okhttp資料快取的流程以及原理。

注意:okhttp只支援get請求的快取,get請求多用於查詢,資料更改沒那麼頻繁,而post請求多使用者資料互動,而且每個快取檔名稱都是用介面的url進行md5加密後生成的,如果post請求的引數更改的話,就沒法考慮到,okhttp設計者就只支援get方式了。如果還是想將post請求資料快取到本地,只能自己另外設計快取策略了。``

設定介面資料快取可以有兩種方式,一種是新增***,另外一種是直接在request.builder類中設定cachecontrol

//新增本地***

.addinterceptor

(new

localcacheinterceptor

(10000))

//設定快取位置,此屬性必須設定

;}設定快取***的好處就是,可以將快取部分,或者說快取策略剝離開來,達到低耦合的效果,自定義的快取***內容如下:

/**

* 此***為攔截本地快取,不會對快取資料造成影響,只會影響到是否能獲取到本地快取資料

*/public

class

localcacheinterceptor

implements

interceptor

@override

public response intercept

(chain chain)

throws ioexception

}catch

(exception e)

}//如果沒有網路,就走快取

cachecontrol =

newcachecontrol.builder()

.maxage

(integer.max_value, timeunit.seconds)

.maxstale

(integer.max_value, timeunit.seconds)

.build()

; request = builder.

cachecontrol

(cachecontrol)

.build()

;return chain.

proceed

(request);}

public

static

boolean

isnetworkconnected()

return

false;}

}

在上面的快取***中,我設定的是,當有網路時,去請求後台資料,沒網路時,走本地的快取資料,當然,這可以根據實際應用場景新增快取策略。比如,我設定一天內不管有沒有網路,都走快取資料等。具體的快取操作,是在cacheinterceptor快取***裡設定的:

public response intercept

(chain chain)

throws ioexception ..

....

return response;

}

最後在自定義的快取資料夾中,檔案截圖如下:

檔名是以請求的url進行md5加密後的32位字串,字尾.0的表示儲存的響應頭資料,字尾.1的表示儲存的響應體body的資料,最後乙個檔案journal,表示檔案快取的歷史記錄。

每一條快取對應兩個狀態副本:dirty,clean。clean表示當前可用的cache。dirty為編輯狀態的cache。由於更新和建立都只操作dirty狀態的副本,實現了讀和寫的分離。

每乙個url對應四個檔案,兩個狀態(diry,clean),每個狀態對應兩個檔案:0檔案對應儲存meta資料,1檔案儲存body資料。

maxage: 資料快取在本地的時間。

maxstale: 多長時間內可以使用快取資料。

cache類本身是final的,說明不能被繼承;所有的方法都是預設的,說明不能被外部呼叫。cache類所有的方法呼叫,都是通過內部實現介面internalcache來的:

final internalcache internalcache =

newinternalcache()

@override

public cacherequest put

(response response)

throws ioexception

@override

public

void

remove

(request request)

throws ioexception

@override

public

void

update

(response cached, response network)

@override

public

void

trackconditionalcachehit()

@override

public

void

trackresponse

(cachestrategy cachestrategy)

};

cache類中對資料的增刪改查操作,其實主要是對disklrucache類的操作,這個從cache類的構造方法就可以看出:

final disklrucache cache;

public

cache

(file directory,

long maxsize)

cache

(file directory,

long maxsize, filesystem filesystem)

接下來,就是主要看okhttp中關於快取的核心類-disklrucache

磁碟快取,通過linkedhashmap實現lru替換;

通過維護本地cache的操作日誌(journal檔案),來保證cache的可見性和原子性;

每乙個cache對應兩個狀態:dirtycleandirty是編輯狀態,更新和插入都是在這個狀態操作的;clean是可用的狀態,查詢是在這個狀態下操作的,從而實現了讀寫分離;

每個url請求對應4個檔案,兩個狀態(dirtyclean),字尾為.0的表示響應頭資料,字尾為.1的表示響應體body資料。

由於快取層對資料的讀寫操作比較多,也是用的okio包,這裡就簡單表述一下okio的讀寫資料的操作吧:

//將資料寫入檔案

void

write2file

(string response)

if(path != null && path.

exists()

)});

}catch

(ioexception e)

finally

catch

(ioexception e)}}

}//從檔案中讀取資料

void

readfromfile()

file file =

newfile

(path,

"b.txt");

if(file.

exists()

) tv.

settext

(sb);}

catch

(ioexception e)

}}

參考文章

okhttp3原始碼分析[disklrucache]

使用okio優化io

okio庫的使用

okhttp快取策略

okhttp原始碼解析(七)–中階之快取機制

Okhttp3原始碼分析之六

了解okhttp的都知道,它提供websocket的使用 宣告okhttp client 建立websocket request request new request.builder url serverurl build websocket client.newwebsocket request...

網路爬蟲之模擬登陸(二)安卓okhttp模擬登陸

之前那個部落格寫的有點錯誤,想想,還是不刪了,以後看到就當是個彎路的教訓okhttpclient client new okhttpclient 這個formbody就寫剛才的引數表裡的內容,鍵值對的形式,有幾條加幾個add 我這裡只是舉個例子,大概寫了兩個鍵值對,大家在寫的時候一定要寫全,有幾條寫...

安卓高階之效能優化全解析(一)

這篇文章作為android效能優化的引入,android的效能優化一直是廣大開發者頭疼的問題,也是非常重要的乙個知識點,這裡面涉及到的知識比較多,不知道大家對效能優化了解多少,首先問一下大家,你所知道的效能優化有多少種?如果是很少關注效能這塊的開發者或者初級程式設計師,可能會一臉懵逼,似曾相識卻又回...