API Reference
NetworkResponse
Sealed class representing all possible network response states.
NetworkResponse.Success
Represents a successful HTTP response (2xx status codes).
data class Success<T : Any>(
val body: T, // The response body
val headers: Headers?, // Response headers
val code: Int // HTTP status code
) : NetworkResponse<T, Nothing>()
Properties:
body: T- The deserialized response bodyheaders: Headers?- HTTP response headerscode: Int- HTTP status code (200-299)
NetworkResponse.ServerError
Represents an HTTP error response from the server (4xx, 5xx status codes).
data class ServerError<U : Any>(
val body: U?, // Parsed error body
val code: Int, // HTTP status code
val headers: Headers? // Response headers
) : NetworkResponse<Nothing, U>()
Properties:
body: U?- The deserialized error body (null if parsing failed)code: Int- HTTP status code (400-599)headers: Headers?- HTTP response headers
NetworkResponse.NetworkError
Represents a network-level error (no internet, timeout, DNS failure, etc.).
data class NetworkError(
val error: IOException // The network error
) : NetworkResponse<Nothing, Nothing>()
Properties:
error: IOException- The underlying network exception
NetworkResponse.UnknownError
Represents any other unexpected error (parsing errors, etc.).
data class UnknownError(
val error: Throwable, // The error
val code: Int?, // HTTP status code (if available)
val headers: Headers? // Response headers (if available)
) : NetworkResponse<Nothing, Nothing>()
Properties:
error: Throwable- The underlying exceptioncode: Int?- HTTP status code if availableheaders: Headers?- HTTP response headers if available
NetworkResponseAdapterFactory
Factory for creating NetworkResponse call adapters.
class NetworkResponseAdapterFactory : CallAdapter.Factory()
Usage:
val retrofit = Retrofit.Builder()
.addCallAdapterFactory(NetworkResponseAdapterFactory())
.build()
Cache Management
CacheManager
Manages caching of network responses using Room database.
class CacheManager(
private val database: AppDatabase,
private val gson: Gson
)
Constructor Parameters:
database: AppDatabase- Room database instancegson: Gson- Gson instance for serialization
Methods:
suspend fun <T> get(key: String, type: Type): T?
suspend fun <T> put(key: String, value: T, type: Type)
suspend fun invalidate(key: String)
suspend fun clear()
CacheConfig
Configuration for cache behavior.
data class CacheConfig(
val strategy: CacheStrategy = CacheStrategy.NETWORK_FIRST,
val maxAgeSeconds: Long = 300,
val forceRefresh: Boolean = false
)
Properties:
strategy: CacheStrategy- The caching strategy to usemaxAgeSeconds: Long- Maximum age of cached data in secondsforceRefresh: Boolean- Force network fetch even if cache is valid
CacheStrategy
Enum defining cache strategies.
enum class CacheStrategy {
NETWORK_FIRST, // Try network first, fallback to cache
CACHE_FIRST, // Use cache if available, otherwise network
NETWORK_ONLY, // Always fetch from network
CACHE_ONLY, // Only use cache
CACHE_WITH_EXPIRY // Use cache if not expired
}
Retry Functions
executeWithRetry
Execute a network call with automatic retry on failure.
suspend fun <T : Any, U : Any> executeWithRetry(
times: Int = 3,
initialDelay: Long = 100,
maxDelay: Long = 1000,
factor: Double = 2.0,
shouldRetry: (NetworkResponse<T, U>) -> Boolean = { it is NetworkResponse.Error },
block: suspend () -> NetworkResponse<T, U>
): NetworkResponse<T, U>
Parameters:
times: Int- Maximum number of retry attemptsinitialDelay: Long- Initial delay in millisecondsmaxDelay: Long- Maximum delay in millisecondsfactor: Double- Multiplier for exponential backoffshouldRetry: (NetworkResponse<T, U>) -> Boolean- Predicate to determine if retry should occurblock: suspend () -> NetworkResponse<T, U>- The network call to execute
Returns: NetworkResponse<T, U> - The final response after retries
executeWithCache
Execute a network call with caching support.
suspend fun <T : Any, U : Any> executeWithCache(
cacheManager: CacheManager,
cacheKey: String,
type: Type,
config: CacheConfig = CacheConfig(),
block: suspend () -> NetworkResponse<T, U>
): NetworkResponse<T, U>
Parameters:
cacheManager: CacheManager- The cache manager instancecacheKey: String- Unique key for this cached datatype: Type- Type token for deserializationconfig: CacheConfig- Cache configurationblock: suspend () -> NetworkResponse<T, U>- The network call to execute
Returns: NetworkResponse<T, U> - The response from cache or network
executeWithRetryAndCache
Execute a network call with both retry and caching support.
suspend fun <T : Any, U : Any> executeWithRetryAndCache(
cacheManager: CacheManager,
cacheKey: String,
type: Type,
config: CacheConfig = CacheConfig(),
times: Int = 3,
initialDelay: Long = 100,
maxDelay: Long = 1000,
factor: Double = 2.0,
block: suspend () -> NetworkResponse<T, U>
): NetworkResponse<T, U>
Parameters: Combination of executeWithRetry and executeWithCache parameters
Returns: NetworkResponse<T, U> - The final response
Extension Functions
invoke()
Operator function to extract the body or return null.
operator fun <T : Any, U : Any> NetworkResponse<T, U>.invoke(): T?
Usage:
val users: List<User>? = apiService.getUsers()()
isFromCache()
Check if the response came from cache.
fun <T : Any, U : Any> NetworkResponse<T, U>.isFromCache(): Boolean
Usage:
if (response.isFromCache()) {
println("Data from cache")
}
onSuccess()
Execute a block if the response is successful.
inline fun <T : Any, U : Any> NetworkResponse<T, U>.onSuccess(
block: (T) -> Unit
): NetworkResponse<T, U>
Usage:
response.onSuccess { users ->
updateUI(users)
}
onError()
Execute a block if the response is an error.
inline fun <T : Any, U : Any> NetworkResponse<T, U>.onError(
block: (Throwable) -> Unit
): NetworkResponse<T, U>
Usage:
response.onError { error ->
showError(error.message)
}
OkHttp Interceptors
CacheInterceptor
Adds cache-control headers to responses.
class CacheInterceptor(
private val maxAgeSeconds: Int = 300
) : Interceptor
Constructor Parameters:
maxAgeSeconds: Int- Maximum age for cached responses
OfflineCacheInterceptor
Enables offline caching when network is unavailable.
class OfflineCacheInterceptor(
private val isNetworkAvailable: () -> Boolean
) : Interceptor
Constructor Parameters:
isNetworkAvailable: () -> Boolean- Function to check network availability
Room Database
AppDatabase
Room database for caching.
@Database(entities = [CacheEntry::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun cacheDao(): CacheDao
}
CacheEntry
Entity representing a cached response.
@Entity(tableName = "cache")
data class CacheEntry(
@PrimaryKey val key: String,
val data: String,
val timestamp: Long,
val headers: String?
)
CacheDao
DAO for cache operations.
@Dao
interface CacheDao {
@Query("SELECT * FROM cache WHERE key = :key")
suspend fun get(key: String): CacheEntry?
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(entry: CacheEntry)
@Query("DELETE FROM cache WHERE key = :key")
suspend fun delete(key: String)
@Query("DELETE FROM cache")
suspend fun clear()
}
Type Aliases
Convenient type aliases for common patterns.
typealias GenericResponse<T> = NetworkResponse<T, ErrorResponse>
typealias EmptyResponse = NetworkResponse<Unit, ErrorResponse>
Usage:
interface ApiService {
@GET("users")
suspend fun getUsers(): GenericResponse<List<User>>
@DELETE("users/{id}")
suspend fun deleteUser(@Path("id") id: Int): EmptyResponse
}