Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Integrating OkHttp3 as the Network Layer for Volley

Tech 1

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

  1. Request Submission: Applications add requests to the queue via RequestQueue.add()
  2. 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
  3. Network Processing: NetworkDispatcher threads execute HTTP requests
  4. 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.

Related Articles

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

SBUS Signal Analysis and Communication Implementation Using STM32 with Fus Remote Controller

Overview In a recent project, I utilized the SBUS protocol with the Fus remote controller to control a vehicle's basic operations, including movement, lights, and mode switching. This article is aimed...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.