
企業工商數據API用哪種?
// 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()
max-age
和 max-stale
是 HTTP 緩存中用來控制響應新鮮度的指令。它們有著不同的含義:
max-age
:指定客戶端認為緩存響應是新鮮的最大時間,以秒為單位。如果響應的年齡超過了 max-age
,客戶端將認為該響應已過期,并嘗試從服務器獲取新的響應。max-stale
:告知客戶端即使響應已過期,仍可接受,但僅在指定的最大過期時間內。同樣以秒為單位。以上是它們的區別。現在我們已經在 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