
Versatile caching solution enabling automatic refresh, expiry handling, and network-aware adjustments. Supports customizable fetching strategies, thread-safe operations, and shared resource management across classes.
A powerful, network-aware caching library for Kotlin Multiplatform that provides intelligent data fetching, automatic refresh, and offline support across Android, iOS, JVM, and Linux platforms.
Add the dependency to your build.gradle.kts:
dependencies {
implementation("com.paoapps.blockedcache:blocked-cache:0.0.8")
}dependencies {
implementation 'com.paoapps.blockedcache:blocked-cache:0.0.8'
}No additional setup required. The library automatically handles Android-specific implementations.
Add the following to your Podfile if using CocoaPods:
pod 'BlockedCache', :git => 'https://github.com/Paoapps/BlockedCache.git', :tag => '0.0.8'Or use Swift Package Manager by adding this repository as a dependency.
No additional setup required. Works out of the box with standard JVM applications.
No additional setup required. Compatible with Linux distributions.
import com.paoapps.blockedcache.*
import kotlinx.coroutines.flow.*
import kotlin.time.Duration.Companion.minutes
// Create a data source (could be database, shared preferences, etc.)
val dataFlow = MutableStateFlow(BlockedCacheData<String>(null, null))
// Create the cache
val cache = BlockedCache<String>(
refreshTime = 5.minutes,
expireTime = 1.hours,
dataFlow = dataFlow,
name = "userProfile"
)
// Fetch data with automatic caching
val resultFlow = cache.getData(
fetcher = {
// Simulate network call
val userData = api.fetchUserProfile()
FetcherResult.Data(userData)
},
updateData = { newData ->
dataFlow.value = newData
}
)
// Collect the results
resultFlow.collect { result ->
when (result) {
is CacheResult.Loading -> showLoading(result.staleData)
is CacheResult.Success -> showData(result.data)
is CacheResult.Error -> showError(result.failure, result.staleData)
is CacheResult.Offline -> showOfflineMessage(result.staleData)
is CacheResult.Empty -> showEmptyState()
}
}import com.paoapps.blockedcache.*
import kotlinx.coroutines.flow.*
// Custom refresh trigger (e.g., pull-to-refresh)
val refreshTrigger = MutableSharedFlow<Unit>()
val cache = BlockedCache<UserData>(
refreshTime = 10.minutes,
expireTime = 2.hours,
trigger = refreshTrigger,
dataFlow = userDataFlow,
name = "userData"
)
// Manual refresh
fun refreshData() {
cache.refresh(forceRefresh = true)
}
// Trigger refresh from UI
refreshTrigger.emit(Unit)import com.paoapps.blockedcache.utils.network.*
// Update network status (implement platform-specific monitoring)
NetworkStatusMonitor.networkStatus.value = NetworkStatus.AVAILABLE
// or
NetworkStatusMonitor.networkStatus.value = NetworkStatus.UNAVAILABLE
val cache = BlockedCache<Data>(
refreshTime = 5.minutes,
dataFlow = dataFlow,
networkStatusFlow = NetworkStatusMonitor.networkStatus
)The main cache class that manages data fetching, caching, and refresh logic.
Parameters:
refreshTime: Time after which data is considered staleexpireTime: Optional time after which data is considered expiredtrigger: Flow of events that trigger cache refreshdataFlow: Flow of cached datanetworkStatusFlow: Flow representing network connectivitynowProvider: Provider for current time (useful for testing)name: Identifier for debuggingisDebugEnabled: Enable debug loggingKey Methods:
getData(): Fetch data with caching logicrefresh(): Manually trigger a refreshSealed class representing cache operation results:
sealed class CacheResult<out T> {
object Empty : CacheResult<Nothing>()
data class Offline<T>(val staleData: T? = null, val creationTimeStaleData: Long? = null) : CacheResult<T>()
data class Loading<T>(val staleData: T? = null, val creationTimeStaleData: Long? = null) : CacheResult<T>()
data class Success<T>(val data: T) : CacheResult<T>()
data class Error<T>(val failure: FetcherResult.Error, val staleData: T? = null, val creationTimeStaleData: Long? = null) : CacheResult<T>()
}Represents the result of a data fetching operation:
sealed class FetcherResult<out T : Any> {
data class Data<T : Any>(val value: T, val origin: String? = null) : FetcherResult<T>()
sealed class Error(val code: Int? = null) : FetcherResult<Nothing>() {
data class Exception(val error: Throwable, val code: Int? = null) : Error()
data class Message(val message: String, val code: Int? = null) : Error()
}
}Container for cached data with metadata:
@Serializable
data class BlockedCacheData<T>(
val data: T? = null,
val creationTime: Long? = null
)This repository includes a comprehensive sample app that demonstrates BlockedCache usage on Android. The shared KMM module generates iOS frameworks that can be integrated into iOS projects.
sample/android module in Android Studio and run the app./gradlew :sample:shared:assemble
build/xcode-frameworks/) into your Xcode projectThe sample app showcases:
sample/
βββ android/ # Android application
β βββ src/main/kotlin/com/paoapps/blockedcache/sample/android/
β βββ build.gradle.kts
βββ shared/ # Shared Kotlin Multiplatform code
β βββ src/commonMain/kotlin/com/paoapps/blockedcache/sample/
β βββ build.gradle.kts
Implement your own data persistence:
// Example with DataStore (Android) or similar
val dataStoreFlow = dataStore.data.map { preferences ->
val json = preferences[USER_DATA_KEY] ?: return@map BlockedCacheData(null, null)
val data = Json.decodeFromString<UserData>(json)
val timestamp = preferences[USER_TIMESTAMP_KEY]
BlockedCacheData(data, timestamp)
}
val cache = BlockedCache(
refreshTime = 15.minutes,
dataFlow = dataStoreFlow,
// ... other parameters
)Use custom NowProvider for testing:
class TestNowProvider : NowProvider {
var currentTime = 1000L
override fun now(): Long = currentTime
}
val testProvider = TestNowProvider()
val cache = BlockedCache(
refreshTime = 5.minutes,
dataFlow = testDataFlow,
nowProvider = testProvider
)
// Control time in tests
testProvider.currentTime = 2000LWe welcome contributions! Please see our Contributing Guide for details.
git clone https://github.com/Paoapps/BlockedCache.git
cd BlockedCacheOpen in your IDE (Android Studio, IntelliJ IDEA, or VS Code with Kotlin plugin)
Run tests:
./gradlew test./gradlew buildThis library is published to Maven Central automatically on every release.
To publish a new version:
library/build.gradle.kts
The release workflow will automatically publish the library to Maven Central.
MIT License
Copyright (c) 2024 PaoApps
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
β Star this repo if you find it useful!
A powerful, network-aware caching library for Kotlin Multiplatform that provides intelligent data fetching, automatic refresh, and offline support across Android, iOS, JVM, and Linux platforms.
Add the dependency to your build.gradle.kts:
dependencies {
implementation("com.paoapps.blockedcache:blocked-cache:0.0.8")
}dependencies {
implementation 'com.paoapps.blockedcache:blocked-cache:0.0.8'
}No additional setup required. The library automatically handles Android-specific implementations.
Add the following to your Podfile if using CocoaPods:
pod 'BlockedCache', :git => 'https://github.com/Paoapps/BlockedCache.git', :tag => '0.0.8'Or use Swift Package Manager by adding this repository as a dependency.
No additional setup required. Works out of the box with standard JVM applications.
No additional setup required. Compatible with Linux distributions.
import com.paoapps.blockedcache.*
import kotlinx.coroutines.flow.*
import kotlin.time.Duration.Companion.minutes
// Create a data source (could be database, shared preferences, etc.)
val dataFlow = MutableStateFlow(BlockedCacheData<String>(null, null))
// Create the cache
val cache = BlockedCache<String>(
refreshTime = 5.minutes,
expireTime = 1.hours,
dataFlow = dataFlow,
name = "userProfile"
)
// Fetch data with automatic caching
val resultFlow = cache.getData(
fetcher = {
// Simulate network call
val userData = api.fetchUserProfile()
FetcherResult.Data(userData)
},
updateData = { newData ->
dataFlow.value = newData
}
)
// Collect the results
resultFlow.collect { result ->
when (result) {
is CacheResult.Loading -> showLoading(result.staleData)
is CacheResult.Success -> showData(result.data)
is CacheResult.Error -> showError(result.failure, result.staleData)
is CacheResult.Offline -> showOfflineMessage(result.staleData)
is CacheResult.Empty -> showEmptyState()
}
}import com.paoapps.blockedcache.*
import kotlinx.coroutines.flow.*
// Custom refresh trigger (e.g., pull-to-refresh)
val refreshTrigger = MutableSharedFlow<Unit>()
val cache = BlockedCache<UserData>(
refreshTime = 10.minutes,
expireTime = 2.hours,
trigger = refreshTrigger,
dataFlow = userDataFlow,
name = "userData"
)
// Manual refresh
fun refreshData() {
cache.refresh(forceRefresh = true)
}
// Trigger refresh from UI
refreshTrigger.emit(Unit)import com.paoapps.blockedcache.utils.network.*
// Update network status (implement platform-specific monitoring)
NetworkStatusMonitor.networkStatus.value = NetworkStatus.AVAILABLE
// or
NetworkStatusMonitor.networkStatus.value = NetworkStatus.UNAVAILABLE
val cache = BlockedCache<Data>(
refreshTime = 5.minutes,
dataFlow = dataFlow,
networkStatusFlow = NetworkStatusMonitor.networkStatus
)The main cache class that manages data fetching, caching, and refresh logic.
Parameters:
refreshTime: Time after which data is considered staleexpireTime: Optional time after which data is considered expiredtrigger: Flow of events that trigger cache refreshdataFlow: Flow of cached datanetworkStatusFlow: Flow representing network connectivitynowProvider: Provider for current time (useful for testing)name: Identifier for debuggingisDebugEnabled: Enable debug loggingKey Methods:
getData(): Fetch data with caching logicrefresh(): Manually trigger a refreshSealed class representing cache operation results:
sealed class CacheResult<out T> {
object Empty : CacheResult<Nothing>()
data class Offline<T>(val staleData: T? = null, val creationTimeStaleData: Long? = null) : CacheResult<T>()
data class Loading<T>(val staleData: T? = null, val creationTimeStaleData: Long? = null) : CacheResult<T>()
data class Success<T>(val data: T) : CacheResult<T>()
data class Error<T>(val failure: FetcherResult.Error, val staleData: T? = null, val creationTimeStaleData: Long? = null) : CacheResult<T>()
}Represents the result of a data fetching operation:
sealed class FetcherResult<out T : Any> {
data class Data<T : Any>(val value: T, val origin: String? = null) : FetcherResult<T>()
sealed class Error(val code: Int? = null) : FetcherResult<Nothing>() {
data class Exception(val error: Throwable, val code: Int? = null) : Error()
data class Message(val message: String, val code: Int? = null) : Error()
}
}Container for cached data with metadata:
@Serializable
data class BlockedCacheData<T>(
val data: T? = null,
val creationTime: Long? = null
)This repository includes a comprehensive sample app that demonstrates BlockedCache usage on Android. The shared KMM module generates iOS frameworks that can be integrated into iOS projects.
sample/android module in Android Studio and run the app./gradlew :sample:shared:assemble
build/xcode-frameworks/) into your Xcode projectThe sample app showcases:
sample/
βββ android/ # Android application
β βββ src/main/kotlin/com/paoapps/blockedcache/sample/android/
β βββ build.gradle.kts
βββ shared/ # Shared Kotlin Multiplatform code
β βββ src/commonMain/kotlin/com/paoapps/blockedcache/sample/
β βββ build.gradle.kts
Implement your own data persistence:
// Example with DataStore (Android) or similar
val dataStoreFlow = dataStore.data.map { preferences ->
val json = preferences[USER_DATA_KEY] ?: return@map BlockedCacheData(null, null)
val data = Json.decodeFromString<UserData>(json)
val timestamp = preferences[USER_TIMESTAMP_KEY]
BlockedCacheData(data, timestamp)
}
val cache = BlockedCache(
refreshTime = 15.minutes,
dataFlow = dataStoreFlow,
// ... other parameters
)Use custom NowProvider for testing:
class TestNowProvider : NowProvider {
var currentTime = 1000L
override fun now(): Long = currentTime
}
val testProvider = TestNowProvider()
val cache = BlockedCache(
refreshTime = 5.minutes,
dataFlow = testDataFlow,
nowProvider = testProvider
)
// Control time in tests
testProvider.currentTime = 2000LWe welcome contributions! Please see our Contributing Guide for details.
git clone https://github.com/Paoapps/BlockedCache.git
cd BlockedCacheOpen in your IDE (Android Studio, IntelliJ IDEA, or VS Code with Kotlin plugin)
Run tests:
./gradlew test./gradlew buildThis library is published to Maven Central automatically on every release.
To publish a new version:
library/build.gradle.kts
The release workflow will automatically publish the library to Maven Central.
MIT License
Copyright (c) 2024 PaoApps
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
β Star this repo if you find it useful!