Advantages of OkHttp and Best Practice Examples
// Add dependencies
implementation("com.squareup.okhttp3:okhttp:4.12.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
—
- Efficient Performance with HTTP/2 Connection Reuse
// In e-commerce applications, batch load product images and details
fun loadProductData() {
val client = OkHttpClient.Builder()
.build()
// Batch request product data
val requests = listOf(
Request.Builder().url("https://api.example.com/products/1").build(),
Request.Builder().url("https://api.example.com/products/1/images").build(),
Request.Builder().url("https://api.example.com/products/1/reviews").build()
)
// Execute requests concurrently (utilizing HTTP/2 connection reuse)
val responses = requests.map { client.newCall(it).execute() }
responses.forEach { println(it.body?.string()) }
}
—
- Automatic Retry and Recovery
// Configure automatic retry strategy
val client = OkHttpClient.Builder()
.retryOnConnectionFailure(true)
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build()
// Automatically retry on request (e.g., during network fluctuations)
val request = Request.Builder()
.url("https://api.example.com/data")
.build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
// Handle retry failure
}
override fun onResponse(call: Call, response: Response) {
// Handle normal response
}
})
—
- Powerful Interceptor Mechanism
// Add logging interceptor (development environment)
val loggingInterceptor = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
val client = OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.build()
// Custom authentication interceptor
class AuthInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val originalRequest = chain.request()
val newRequest = originalRequest.newBuilder()
.header("Authorization", "Bearer $token")
.build()
return chain.proceed(newRequest)
}
}
// Add custom interceptor
val client = OkHttpClient.Builder()
.addInterceptor(AuthInterceptor())
.build()
—
- Proper Use of Caching
// Configure caching strategy (image browsing application)
val cacheDir = File(context.cacheDir, "http_cache")
val cacheSize = 10 * 1024 * 1024L // 10MB cache
val client = OkHttpClient.Builder()
.cache(Cache(cacheDir, cacheSize))
.build()
// Set cache control header
val request = Request.Builder()
.url("https://api.example.com/images/photo.jpg")
.header("Cache-Control", "public, max-age=86400") // Cache for 1 day
.build()
// Request will prioritize using cache
client.newCall(request).execute().use { response ->
println(response.body?.string())
}
—
- WebSockets for Real-Time Communication
// WebSocket connection in chat application
val client = OkHttpClient()
val request = Request.Builder().url("ws://echo.websocket.org").build()
val wsListener = object : WebSocketListener() {
override fun onOpen(webSocket: WebSocket, response: Response) {
webSocket.send("Hello, Server!")
}
override fun onMessage(webSocket: WebSocket, text: String) {
println("Received: $text")
}
override fun onFailure(webSocket: WebSocket, cause: Throwable, response: Response?) {
cause.printStackTrace()
}
}
val ws = client.newWebSocket(request, wsListener)
—
- Asynchronous Requests and Callbacks
// Asynchronously load data (avoid blocking the main thread)
val client = OkHttpClient()
val request = Request.Builder()
.url("https://api.example.com/data")
.build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
// Handle error in background thread
Log.e("OkHttp", "Request failed", e)
}
override fun onResponse(call: Call, response: Response) {
// Handle response in background thread
val data = response.body?.string()
// Switch to main thread to update UI
runOnUiThread {
textView.text = data
}
}
})
—
- Regular Updates and Security
// Check for OkHttp version updates
val latestVersion = "4.12.0" // Obtain from Gradle plugin or release page
if (currentVersion < latestVersion) {
// Notify user to update dependencies
Log.w("OkHttp", "New version available: $latestVersion")
}
// Configure HTTPS security policy
val client = OkHttpClient.Builder()
.sslSocketFactory(sslSocketFactory, trustManager)
.hostnameVerifier { hostname, session -> hostname in trustedHosts }
.build()
—
Other Best Practices
- Thread Safety: OkHttp is thread-safe and can be globally reused as a single instance.
- Resource Release: The `Response` object must be released using `use {}` or `close()`.
- Timeout Configuration: Adjust timeout based on business scenarios (e.g., extend timeout for video streaming).
- Error Handling: Add retry logic for `5xx` errors and log `4xx` errors.
By following these practices, you can fully leverage the performance advantages of OkHttp in actual projects while ensuring code maintainability and robustness.