In this article, WE will analyze the source code of okHTTP from the perspective of the overall framework.

Okhttp framework source address: github.com/square/okht…

How do I use okHTTP

OkHttpClient client = new OkHttpClient.Builder().build();
Request request = new Request.Builder().
        url("https://github.com/cozing"). build(); Call call = client.newCall(request); Try {//1. Synchronize request mode Response Response = call.execute(); //2. Call. Enqueue (newCallback() {
        @Override
        public void onFailure(Call call, IOException e) {
            Log.info("cozing"."Transaction failed.");
        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
            Log.info("cozing"."Successful transaction."); }}); } catch (IOException e) { e.printStackTrace(); }Copy the code

Here is a simple communication flow using OKHTTP that includes both synchronous and asynchronous requests:

  1. The method that the synchronous request calls iscall.execute()Internally, thread blocking is used to directly return the result to Response, which we will explain in detail later;
  2. The method invoked by an asynchronous request iscall.enqueue(Callback callback)The method needs to pass in an interface where the Callback waits for the result CallbackFail onFailure () ()andOnResponse () ()In the back.

So, let’s take a look at the overall flow of okHTTP source code.

Overall architecture Flow chart

Let’s take a look at okHTTP’s internal implementation based on this overall architecture diagram.

The process walkthrough

Create OkHttpClient

Start by creating the OkHttpClient object, which is the client of the OKHTTP framework for sending HTTP Requests and reading Responses from transactions. The official recommendation is to use a singleton to create an OkHttpClient, that is, only once in a process, and each subsequent transaction will be sent using that instance. This is because OkHttpClient has its own connection pool and thread pool, which can be reused to reduce latency and save memory. If we created an OkHttpClient for each transaction, we would waste a lot of memory resources.

Creation method:

OkHttpClient client = new OkHttpClient.Builder().build();
Request request = new Request.Builder().
        url("https://github.com/cozing").
        build();
Call call = client.newCall(request);
Copy the code

There is another way to create an OkHttpCleint object:

OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().
        url("https://github.com/cozing").
        build();
Call call = client.newCall(request);
Copy the code

The first creates an OkHttpClient object in Builder mode, which allows you to customize every parameter attribute inside the Builder. The second creates an OkHttpClient object in normal instance creation mode, which creates a default Builder internally. So this approach uses the internal properties of the default Builder.

Creating a Call object

A Call object represents a request, and each transaction request produces a new Call. Call is actually an interface object, and its concrete implementation class is RealCall

Call creation process:

Request request = new Request.Builder().
        url("https://github.com/cozing").
        build();
Call call = client.newCall(request);
Copy the code

Call (); Request (); Request (); Request (); Request ();

  • Url: transaction request address;
  • Method: Request methods, such as GET, POST, HTTP… Such as request mode;
  • Headers: request headers;
  • Body: request body;

NewCall (request); newCall(request);

RealCall()

RealCall

Request trading

Okhttp provides two types of requests: a synchronous request and an asynchronous request. Call.execute () is called for synchronous requests, call.enQueue (Callback Callback) is called for asynchronous requests,

Before we look at the implementation of the two request methods, let’s look at an important member of okHTTP, the Dispatcher:

Dispatcher(Dispatcher)

Dispatcher is the core class of okHTTP task scheduling. It is responsible for managing synchronous and asynchronous requests and managing the request status of each request task. It also maintains a thread pool for executing corresponding requests.

Dispatcher
readyAsyncCalls
promoteCall()
runningAsyncCalls

Let’s take a look at the implementation of synchronous and asynchronous requests and explain in detail how they are implemented.

Synchronous transaction request

Call.execute ()

Dispatcher
executed()

RealCall
Deque
Deque
Deque

Client.dispatcher ().finished(this) is called in finally to remove the request from the queue regardless of the result of the request.

The next call to getResponseWithInterceptorChain () method:

Asynchronous transaction request

Call. enqueue(Callback Callback)

dispatcher
equeue(new AsyncCall(responseCallback))
AsyncCall

Dispatcher equeUE (New AsyncCall(responseCallback))

executorService()
execute(call)
redyAsncCalls.add(call)
call
readyAsyncCalls
readyAsyncCalls

ExecutorService ().execute(call)

The call implementation object type is AsyncCall.

AsyncCall
RealCall
NamedRunnable
NamedRunnable

AsyncCall
Runnable
run()
AsyncCall
execute()
execute()
getResponseWithInterceptorChain()

GetResponseWithInterceptorChain ()/interceptor chain

Through the analysis of the above we know whether a synchronous or asynchronous request, finally will go getResponseWithInterceptorChain () method, getResponseWithInterceptorChain () is one of the essence of design in okhttp, So let’s look at the internal implementation of this method:

These interceptors include:

  1. User-defined interceptor
  2. RetryAndFollowUpInterceptor: retry and redirect interceptors, reconnection is mainly responsible for the network failure.
  3. BridgeInterceptor: Is responsible for adding the transaction request header.
  4. CacheInterceptor: a CacheInterceptor that intercepts caches.
  5. ConnectInterceptor: Network connection interceptor. It is responsible for formally opening HTTP requests.
  6. CallServerInterceptor: Sends network requests and reads network responses.

For details on the implementation and internal flow of each interceptor, you can read the source code for yourself. In this article, we will focus on the overall architecture of OKHTTP.

Proceed () (RealInterceptorChain); proceed();

intercept(next)
response
The next interceptor depends on the return of the current interceptor to ensure that the interceptors are executed sequentially.

Results executed in the interceptor chain are returned directly in response in synchronous requests, whereas in asynchronous requests:

Callback
onReponse

conclusion

At this point, okHTTP overall architecture analysis is completed, it is suggested that you can follow the source code step by step to understand, to understand okHTTP design ideas, and then applied to the project development. Of course, OKHTTP is a very large framework, this article mainly from its overall architecture to do a simple analysis of it, the internal implementation logic and ideas are worth careful thinking and savor.

Pay attention and don’t get lost

The article continues to update every week, you can wechat search “ten minutes to learn programming” the first time to read and urge more, if this article is written well, feel something ~ for praise 👍 for attention ❤️ for share ❤️ everyone’s support and recognition, is the biggest power of my creation, we see the next article!