// Defining a cache of 5 MB size
val cacheSize = (5 * 1024 * 1024).toLong()

//Initializing instance of Cache class
val myCache = Cache(context.cacheDir, cacheSize)

//defining okhttpclient instance
val okHttpClient = OkHttpClient.Builder()
.cache(myCache)
.build()

定義緩存規則

根據設備是否連接到互聯網,讓我們來定義一些基本的網絡緩存規則:

你可以為你的項目定義不同且更為細致的規則來應對復雜的情況,但為了簡單起見,我們將采用上述規則。

第一步是檢查用戶是否連接到互聯網。為此,我們可以使用 ConnectivityManager 類收集數據并檢查用戶是否連接到互聯網。讓我們來定義一個名為 hasNetwork() 的函數,如下所示:

//CheckNetwork.kt
fun hasNetwork(context: Context): Boolean {
val connectivityManager = context
.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val nw = connectivityManager.activeNetwork ?: return false
val actNw = connectivityManager.getNetworkCapabilities(nw) ?: return false
return when {
actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
actNw.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH) -> true
else -> false
}
}

我們檢查用戶是否連接到WiFi、蜂窩移動網絡或藍牙網絡,并根據情況返回true或false。

為了實現我們緩存規則的定義,我們將使用 OkHttp 庫中的一個組件,叫做 Interceptor。攔截器是一個強大的機制,允許您在應用程序發送或接收 HTTP 請求和響應之前攔截、處理甚至修改它們。它們在通信流程中起到中間人的作用,讓您更加靈活地控制 OkHttp 處理網絡請求的方式。

在攔截器中,我們將提供指導,告訴我們的 okHttpClient 實例何時使用緩存響應。

在構建客戶端實例時,讓我們使用 addInterceptor() 函數來添加攔截器。我們可以在這個函數中修改我們的 API 請求。在 lambda 函數中,我們可以獲取請求對象,并在最終發送到服務器之前對其進行修改。為了添加緩存功能,我們使用 cacheControl() 函數,該函數接受 CacheControl 類的參數。

我們需要實現的第一條規則是,如果設備連接到互聯網,則使用 30 分鐘前的響應(如果有的話),否則獲取新的響應。我們使用 maxAge() 函數來實現這一點。

我們需要實現的第二條規則是,如果設備斷開連接,則使用最多 1 天前的響應。為此,我們使用 maxStale() 函數。

// Defining a cache of 5 MB size
val cacheSize = (5 * 1024 * 1024).toLong()

//Initializing instance of Cache class
val myCache = Cache(context.cacheDir, cacheSize)

//defining okhttpclient instance
val okHttpClient = OkHttpClient.Builder()
.cache(myCache)
.addInterceptor { chain ->
var request = chain.request()
request = if (hasNetwork(context))
request
.newBuilder()
.cacheControl(
CacheControl.Builder()
.maxAge(30, TimeUnit.MINUTES)
.build()
)
.build()
else
request
.newBuilder()
.cacheControl(
CacheControl.Builder()
.maxStale(1, TimeUnit.DAYS)
.build()
)
.build()
chain.proceed(request)
}
.build()

maxAge() 與 maxStale() 的區別

max-age 和 max-stale 是 HTTP 緩存中用來控制響應新鮮度的指令。它們有著不同的含義:

以上是它們的區別。現在我們已經在 OkHttpClient 中實現了緩存系統,是時候為你的項目構建一個快速可靠的用戶體驗了。如果你使用 Retrofit 作為 OkHttp 的封裝器,也可參考以下代碼片段來實現緩存!

//RetrofitClient.kt 
class RetrofitClient(private val context: Context) {
val cacheSize = (5 * 1024 * 1024).toLong()

val instance: Api by lazy {
val myCache = Cache(context.cacheDir, cacheSize)

val okHttpClient = OkHttpClient.Builder()
.cache(myCache)
.addInterceptor { chain ->
var request = chain.request()
request = if (hasNetwork(context))
request
.newBuilder()
.cacheControl(
CacheControl.Builder()
.maxAge(30, TimeUnit.MINUTES)
.build()
)
.build()
else
request
.newBuilder()
.cacheControl(
CacheControl.Builder()
.maxStale(1, TimeUnit.DAYS)
.build()
)
.build()
chain.proceed(request)
}
.addInterceptor(HttpLoggingInterceptor().apply {
this.level = HttpLoggingInterceptor.Level.BODY }
)
.build()

val retrofit = Retrofit.Builder()
.baseUrl("BASE_URL")
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build()

retrofit.create(Api::class.java)
}
}

現在,你可以開始在實際設備或模擬器上運行你的項目了。要檢查緩存是否有效,請使用Android Studio中的App Inspection標簽頁,或者使用OkHttp的日志攔截器來記錄所有網絡調用。

結論

對于長時間不變的API響應,可以通過上述技術進行緩存,從而節省大量資源。軟件開發始終涉及根據時間和空間做出一定的權衡。在這種情況下,我們為了節省時間而犧牲了一點空間(用于存儲API響應)。

本文章轉載微信公眾號@虎哥Lovedroid

上一篇:

Zabbix API開發實戰,創建報警媒介和代碼示例

下一篇:

用gin寫簡單的crud后端API接口
#你可能也喜歡這些API文章!

我們有何不同?

API服務商零注冊

多API并行試用

數據驅動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內容創意新穎性、情感共鳴力、商業轉化潛力

25個渠道
一鍵對比試用API 限時免費

#AI深度推理大模型API

對比大模型API的邏輯推理準確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費