Mobile Development 15 min read

Understanding OkHttp: Request Flow, Dispatcher, Interceptors, Connection Reuse, and Design Patterns

This article provides a comprehensive overview of OkHttp, covering its overall request process, the role of the dispatcher, how application and network interceptors work, TCP connection reuse via the connection pool, idle‑connection cleanup, key advantages, and the design patterns employed in the framework.

Top Architect
Top Architect
Top Architect
Understanding OkHttp: Request Flow, Dispatcher, Interceptors, Connection Reuse, and Design Patterns

OkHttp is one of the most widely used HTTP client libraries in Android development, known for its ease of use, extensibility, and powerful features, making it a frequent topic in technical interviews.

OkHttp Request Overall Flow

A simple request involves creating an OkHttpClient and a Request , then calling newCall(request).enqueue(...) . Although the code appears straightforward, the framework performs extensive internal processing.

val okHttpClient = OkHttpClient()
val request: Request = Request.Builder()
    .url("https://www.google.com/")
    .build()

okHttpClient.newCall(request).enqueue(object : Callback {
    override fun onFailure(call: Call, e: IOException) { }
    override fun onResponse(call: Call, response: Response) { }
})

The request first passes through the dispatcher, which manages queues and thread pools, then proceeds through a chain of interceptors that handle retries, caching, connection establishment, and more.

OkHttp Dispatcher

The dispatcher maintains a running queue and a ready queue. For synchronous calls it simply records the request; for asynchronous calls it limits concurrent requests (default max 64 overall, max 5 per host) and schedules execution via a thread pool.

synchronized void enqueue(AsyncCall call) {
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
        runningAsyncCalls.add(call)
        executorService().execute(call)
    } else {
        readyAsyncCalls.add(call)
    }
}

OkHttp Interceptors

After dispatching, the request traverses five default interceptors forming a responsibility chain. Application interceptors run first (user‑defined request modifications) and network interceptors run later (e.g., connection handling, response processing).

internal fun getResponseWithInterceptorChain(): Response {
    val interceptors = mutableListOf
()
    interceptors += client.interceptors
    interceptors += RetryAndFollowUpInterceptor(client)
    interceptors += BridgeInterceptor(client.cookieJar)
    interceptors += CacheInterceptor(client.cache)
    interceptors += ConnectInterceptor
    if (!forWebSocket) interceptors += client.networkInterceptors
    interceptors += CallServerInterceptor(forWebSocket)
    val chain = RealInterceptorChain(this, interceptors, 0)
    return chain.proceed(originalRequest)
}

The chain ensures each interceptor can process or short‑circuit the request, with application interceptors typically used for logging and network interceptors for low‑level data handling.

TCP Connection Reuse

OkHttp’s ConnectInterceptor manages TCP connections. It first tries to reuse an existing connection, then checks the connection pool, and finally creates a new RealConnection if needed, supporting HTTP/1.1 keep‑alive and HTTP/2 multiplexing.

private RealConnection findConnection(...): RealConnection {
    synchronized(connectionPool) {
        // 1. Try assigned connection
        // 2. Try pooled connection
        // 3. Try pooled connection with routes (HTTP/2)
        // 4. Create new connection and handshake
        // 5. Final pool check for multiplexing
    }
    return result
}

Idle Connection Cleanup

The connection pool runs a cleanup task that periodically scans connections, removes those idle longer than the keep‑alive timeout (default 5 minutes) or when the idle count exceeds the configured limit, and closes their sockets.

private long cleanup(long now) {
    int inUse = 0, idle = 0
    RealConnection longestIdle = null
    long longestIdleDuration = Long.MIN_VALUE
    synchronized(this) {
        for (RealConnection conn : connections) {
            if (pruneAndGetAllocationCount(conn, now) > 0) {
                inUse++
                continue
            }
            idle++
            long idleDuration = now - conn.idleAtNanos
            if (idleDuration > longestIdleDuration) {
                longestIdleDuration = idleDuration
                longestIdle = conn
            }
        }
        if (longestIdleDuration >= keepAliveDurationNs || idle > maxIdleConnections) {
            connections.remove(longestIdle)
        } else if (idle > 0) {
            return keepAliveDurationNs - longestIdleDuration
        } else if (inUse > 0) {
            return keepAliveDurationNs
        } else {
            cleanupRunning = false
            return -1
        }
    }
    closeQuietly(longestIdle.socket())
    return 0
}

Advantages of OkHttp

Simple API using the Builder pattern.

Highly extensible via custom application and network interceptors.

Supports multiple protocols (HTTP/1.1, HTTP/2, SPDY, WebSocket).

Connection pooling reduces latency.

Automatic GZIP compression.

Built‑in caching to avoid redundant network calls.

Automatic retries and redirects.

Design Patterns Used

Builder pattern for OkHttpClient and Request .

Facade pattern to expose a simple client interface.

Chain of Responsibility for the interceptor chain.

Flyweight (object pool) for TCP connections and thread pools.

The article concludes with a call for discussion, a QR‑code for a special gift, and links to additional resources.

design patternsAndroidnetworkConnection PoolKotlinInterceptorOkHttp
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.