KNET oferuje różne rozwiązania cache: cache w pamięci (KNETResponseCache), persistent cache na dysku (KNETPersistentCache) oraz warunkowy cache (KNETConditionalCache).
import rip.nerd.kitsunenet.interceptor.KNETCacheInterceptor
// Automatyczny cache dla requestów GET/HEAD via interceptor
val client = KNETClient.builder()
.addInterceptor(KNETCacheInterceptor(
maxAge = 300_000, // TTL 5 minut
maxSize = 100 // maks. 100 wpisów
))
.build()
// Metody fabryczne
val client = KNETClient.builder()
.addInterceptor(KNETCacheInterceptor.shortLived()) // 1 minuta
.build()
KNETCacheInterceptor.mediumLived() // 5 minut
KNETCacheInterceptor.longLived() // 1 godzina
// Nagłówek X-KNET-Cache dodawany automatycznie:
// X-KNET-Cache: HIT (z cache)
// X-KNET-Cache: MISS (z sieci)
import rip.nerd.kitsunenet.cache.KNETResponseCache
val cache = KNETResponseCache(
maxSize = 100, // Maks. 100 wpisów
defaultTtlMs = 300_000 // TTL 5 minut
)
// Zapisz odpowiedź
cache.put("https://api.example.com/users", response)
// Zapisz z własnym TTL
cache.put("https://api.example.com/users", response, ttlMs = 60_000)
// Pobierz
val cached = cache.get("https://api.example.com/users")
// Pobierz lub wykonaj request (async)
val response = cache.getOrPut("https://api.example.com/users") {
client.get("https://api.example.com/users")
}
// Usuń wpis
cache.remove("https://api.example.com/users")
// Usuń po wzorcu
cache.removeByPattern(Regex(".*api.example.com/users.*"))
// Wyczyść wszystko
cache.clear()
// Sprawdź czy klucz istnieje (i nie wygasł)
val exists = cache.contains("https://api.example.com/users")
// Metody fabryczne
KNETResponseCache.shortLived() // TTL 30s, 50 wpisów
KNETResponseCache.longLived() // TTL 5 min, 200 wpisów
KNETResponseCache.staticResources() // TTL 1 godzina, 500 wpisów
import rip.nerd.kitsunenet.cache.KNETPersistentCache
// Przetrwa restart aplikacji - zapisany w SharedPreferences
val cache = KNETPersistentCache.Builder(context)
.maxMemoryEntries(100)
.maxDiskEntries(500)
.defaultTtlMs(3600_000) // 1 godzina
.encryptData(true) // Opcjonalnie: szyfrowanie danych
.build()
// Zapisz odpowiedź
cache.put("users_list", response)
cache.put("user_profile", response, ttlMs = 86400_000) // 24h
// Pobierz odpowiedź
val cached = cache.getResponse("users_list")
// Pobierz lub wykonaj request
val response = cache.getOrFetch("users_list") {
client.get("https://api.example.com/users")
}
// Invalidacja
cache.invalidate("users_list")
cache.invalidateByPrefix("user_")
cache.invalidateAll()
// Stałe TTL
KNETPersistentCache.TTL.SHORT // 1 minuta
KNETPersistentCache.TTL.MEDIUM // 5 minut
KNETPersistentCache.TTL.LONG // 1 godzina
KNETPersistentCache.TTL.VERY_LONG // 24 godziny
KNETPersistentCache.TTL.WEEK // 7 dni
import rip.nerd.kitsunenet.cache.KNETConditionalCache
val conditionalCache = KNETConditionalCache()
// Automatycznie używa If-None-Match / If-Modified-Since
// Jeśli serwer zwróci 304 Not Modified, zwraca cached response
val response = conditionalCache.getWithValidation(client, request)
// ETag i Last-Modified są zapisywane i wysyłane automatycznie
val stats = cache.getStats()
println("Wpisy: ${stats.size} / ${stats.maxSize}")
println("Trafienia: ${stats.hits}")
println("Chybienia: ${stats.misses}")
println("Hit rate: ${String.format("%.1f", stats.hitRate * 100)}%")
println(stats.format())
// Załaduj cache przed interakcją użytkownika
suspend fun warmCache() {
val urls = listOf(
"https://api.example.com/config",
"https://api.example.com/categories",
"https://api.example.com/featured"
)
urls.forEach { url ->
try {
val response = client.get(url)
cache.put(url, response)
} catch (e: Exception) {
Log.w("Cache", "Błąd wstępnego ładowania: $url")
}
}
}
class OfflineFirstRepository(
private val client: KNETClient,
private val cache: KNETPersistentCache,
private val networkChecker: NetworkChecker
) {
suspend fun getUsers(): List<User> {
// 1. Sprawdź cache
val cached = cache.getResponse("users")
// 2. Jeśli offline, zwróć cache
if (!networkChecker.isOnline()) {
return cached?.jsonList() ?: emptyList()
}
// 3. Pobierz z sieci
return try {
val response = client.get("$baseUrl/users")
// 4. Zapisz do cache
cache.put("users", response)
response.jsonList()
} catch (e: Exception) {
// 5. Fallback do cache
cached?.jsonList() ?: throw e
}
}
}