okhttp3 request process analysis

1. Simple get request

        String url = "https://www.baidu.com/";
        OkHttpClient okHttpClient = new OkHttpClient();
        Request request = new Request.Builder().url(url).build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {

                Log.d(TAG, "onResponse: response="+response.toString());
            }
        });

One: Create an OkHttpClient object

        OkHttpClient okHttpClient = new OkHttpClient(); 

okhttp source code

       public OkHttpClient() {
         this(new Builder());
    }

When the OkHttpClient object is created and the builder object is constructed by default for initialization
2 : Initialize the request object

        Request request = new Request.Builder().url(url).build();

Request: Every network request is a request. Request is the encapsulation of url, method, header, and body, as well as the encapsulation of the request line, request header and entity content in the http protocol. Belongs to the builder pattern.
Three: make a request

@Override 
public Call newCall(Request request) {
    return new RealCall(this, request, false /* for web socket */);
  }

RealCall is an implementation of the Call interface

final class RealCall implements Call {
 RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    final EventListener.Factory eventListenerFactory = client.eventListenerFactory();

    this.client = client;
    this.originalRequest = originalRequest;
    this.forWebSocket = forWebSocket;
    this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);

    // TODO(jwilson): this is unsafe publication and not threadsafe.
    this.eventListener = eventListenerFactory.create(this);
  }
}

Execution process of asynchronous requests

@Override public void enqueue(Callback responseCallback) {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }

It can be seen from the above:
1. Check whether the call has been executed, each call can only be executed once
2. Use client.dispatcher().enqueue(this) for actual execution, client.dispatcher() is as follows

public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory {
    public Dispatcher dispatcher() {
        return dispatcher;
      }
}

3.AsyncCall is an inner class of RealCall and inherits NamedRunnable

final class AsyncCall extends NamedRunnable {
    private final Callback responseCallback;

    AsyncCall(Callback responseCallback) {
      super("OkHttp %s", redactedUrl());
      this.responseCallback = responseCallback;
    }
 }

The NamedRunnable class is as follows:

public abstract class NamedRunnable implements Runnable {
  protected final String name;

  public NamedRunnable(String format, Object... args) {
    this.name = Util.format(format, args);
  }

  @Override public final void run() {
    String oldName = Thread.currentThread().getName();
    Thread.currentThread().setName(name);
    try {
      execute();
    } finally {
      Thread.currentThread().setName(oldName);
    }
  }

  protected abstract void execute();
}

It can be seen from the above that NameRunnable implements the Runnable interface and is an abstract class whose abstract method is execute(), and its subclasses should implement the execute method.

final class RealCall implements Call {
    final class AsyncCall extends NamedRunnable {
    //实现execute方法
         @Override protected void execute() {
          boolean signalledCallback = false;
          try {
            Response response = getResponseWithInterceptorChain();
            if (retryAndFollowUpInterceptor.isCanceled()) {
              signalledCallback = true;
              responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
            } else {
              signalledCallback = true;
              responseCallback.onResponse(RealCall.this, response);
            }
          } catch (IOException e) {
            if (signalledCallback) {
              // Do not signal the callback twice!
              Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
            } else {
              responseCallback.onFailure(RealCall.this, e);
            }
          } finally {
            client.dispatcher().finished(this);
          }
        }
       }
 }

It can be seen from the above that AsyncCall implements the execute method. First, the getResponseWithInterceptorChain() method is called to obtain the response. After the acquisition is successful, the onReponse method of the callback is called. If it fails, the onFailure method of the callback is called. Finally, call the finished method of the Dispatcher.

public final class Dispatcher {
 /** Ready async calls in the order they'll be run.  准备将要执行的请求*/
  private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();

  /** Running asynchronous calls. Includes canceled calls that haven't finished yet.正在执行的异步请求,包含已经取消但未执行完的请求 */
  private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();

//client.dispatcher().enqueue(new AsyncCall(responseCallback))源码
//如果当前还能执行一个并发请求,则加入 runningAsyncCalls ,立即执行,否则加入 readyAsyncCalls 队列
    synchronized void enqueue(AsyncCall call) {
        if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
          runningAsyncCalls.add(call);
          executorService().execute(call);
        } else {
          readyAsyncCalls.add(call);
        }
     }

      //client.dispatcher().finished(this)源码

       void finished(AsyncCall call) {
        finished(runningAsyncCalls, call, true);
       }
       //将正在运行的任务Call从队列runningAsyncCalls中移除
      private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
        int runningCallsCount;
        Runnable idleCallback;
        synchronized (this) {
          if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
          if (promoteCalls) promoteCalls();
          runningCallsCount = runningCallsCount();
          idleCallback = this.idleCallback;
        }

        if (runningCallsCount == 0 && idleCallback != null) {
          idleCallback.run();
        }
      }
//构造了单例线程池
     public synchronized ExecutorService executorService() {
        if (executorService == null) {
          executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
              new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
        }
        return executorService;
      }
 }

Thread pool constructor

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }

corePoolSize: the minimum number of concurrent threads, if it is 0, all threads will be destroyed after a period of idle time
maximumPoolSize: the maximum number of threads, the maximum number of threads that can be expanded when the task comes in, when it is greater than this value, it will be discarded according to the processing mechanism To handle keepAliveTime : when the number of threads is greater than corePoolSize
, the maximum survival time of redundant idle threads A thread pool with a core of [0, Integer.MAX_VALUE], it does not reserve any minimum number of threads, and creates more threads at any time. When a thread is idle, it can only live for 60 seconds.



Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325650962&siteId=291194637