Integrating OkHttp3 as the Network Layer for Volley
Implementing a Custom OkHttpStack for Volley
public class OkHttpStack extends HurlStack {
private final OkHttpClient baseClient;
public OkHttpStack(OkHttpClient client) {
this.baseClient = client;
}
private void configureRequestMethod(okhttp3.Request.Builder builder, Request<?> volleyRequest)
throws AuthFailureError {
switch (volleyRequest.getMethod()) {
case Request.Method.GET:
builder.get();
break;
case Request.Method.POST:
builder.post(createBodyContent(volleyRequest));
break;
case Request.Method.PUT:
builder.put(createBodyContent(volleyRequest));
break;
case Request.Method.DELETE:
builder.delete();
break;
case Request.Method.HEAD:
builder.head();
break;
case Request.Method.PATCH:
builder.patch(createBodyContent(volleyRequest));
break;
default:
throw new IllegalStateException("Unsupported HTTP method");
}
}
private RequestBody createBodyContent(Request request) throws AuthFailureError {
byte[] requestBody = request.getBody();
if (requestBody == null) return null;
return RequestBody.create(MediaType.parse(request.getBodyContentType()), requestBody);
}
@Override
public HttpResponse executeRequest(Request<?> volleyRequest, Map<String, String> extraHeaders)
throws IOException, AuthFailureError {
OkHttpClient client = baseClient.newBuilder()
.readTimeout(volleyRequest.getTimeoutMs(), TimeUnit.MILLISECONDS)
.connectTimeout(volleyRequest.getTimeoutMs(), TimeUnit.MILLISECONDS)
.build();
okhttp3.Request.Builder httpRequest = new okhttp3.Request.Builder();
// Set headers from Volley request
for (Map.Entry<String, String> header : volleyRequest.getHeaders().entrySet()) {
httpRequest.addHeader(header.getKey(), header.getValue());
}
// Set additional headers
for (Map.Entry<String, String> header : extraHeaders.entrySet()) {
httpRequest.addHeader(header.getKey(), header.getValue());
}
configureRequestMethod(httpRequest, volleyRequest);
httpRequest.url(volleyRequest.getUrl());
Response httpResponse = client.newCall(httpRequest.build()).execute();
ProtocolVersion protocol = new ProtocolVersion("HTTP",
httpResponse.protocol() == Protocol.HTTP_1_0 ? 1 : 2, 0);
StatusLine status = new BasicStatusLine(protocol, httpResponse.code(), httpResponse.message());
BasicHttpResponse response = new BasicHttpResponse(status);
response.setEntity(createEntity(httpResponse));
// Copy response headers
Headers headers = httpResponse.headers();
for (int i = 0; i < headers.size(); i++) {
response.addHeader(new BasicHeader(headers.name(i), headers.value(i)));
}
return response;
}
}
Initializing Volley with OkHttp3
OkHttpClient httpClient = new OkHttpClient.Builder().build();
RequestQueue volleyQueue = Volley.newRequestQueue(context, new OkHttpStack(httpClient));
Volley Arhcitecture Overview
Volley employs a multi-threaded architecture consisting of:
- UI Thread: Handles request submission and result processing
- Cache Thread: Manages cache lookup operations
- Network Thread Pool: Processes actual HTTP requests (default size: 4 threads)
Request Processing Flow
- Request Submission: Applications add requests to the queue via
RequestQueue.add() - Cache Check: CacheDispatcher thread checks if response exists in cache
- Cache hit: Returns cached response to main thread
- Cache miss: Queues request for network processing
- Network Processing: NetworkDispatcher threads execute HTTP requests
- Response Handling: Parsed responses are delivered to main thread callbacks
Core Components
- HttpStack: Abstract layer for HTTP implementations (HurlStack/HttpClientStack)
- Network: Intterface for executing network requests
- Cache: Storage mechanism for response caching (DiskBasedCache default)
Queue Initialization Code
public static RequestQueue createRequestQueue(Context ctx, HttpStack stack, int cacheSize) {
File cacheDirectory = new File(ctx.getCacheDir(), "volley");
if (stack == null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
stack = new HurlStack();
} else {
stack = new HttpClientStack(AndroidHttpClient.newInstance("volley/1.0"));
}
}
Network network = new BasicNetwork(stack);
RequestQueue queue = new RequestQueue(
new DiskBasedCache(cacheDirectory, cacheSize),
network
);
queue.start();
return queue;
}
Thread Management
public void start() {
// Initialize cache dispatcher
mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);
mCacheDispatcher.start();
// Start network dispatchers
for (int i = 0; i < mDispatchers.length; i++) {
NetworkDispatcher worker = new NetworkDispatcher(mNetworkQueue, mNetwork, mCache, mDelivery);
mDispatchers[i] = worker;
worker.start();
}
}
Key Design Patterns
Volley uses a producer-consumer pattern where:
- Main thread produces requests
- Cache/Network threads consume and process requests
- ResponseDelivery handles callback execution on main thread
Cache keys are generated using HTTP method + URL combination, enabling intelligent caching strategies.