美文网首页
Okhttp原理

Okhttp原理

作者: 晓晓桑 | 来源:发表于2019-11-08 00:46 被阅读0次

    异步get

        private void getData() {
    
            String url = "https://wwww.baidu.com";
    
            OkHttpClient okHttpClient = new OkHttpClient.Builder()
                    .build();
    
            final Request request = new Request.Builder()
                    .url(url)
                    .get()
                    .build();
    
            Call call = okHttpClient.newCall(request);
            call.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    Log.d(TAG, "onFailure: ");
                }
    
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    Log.d(TAG, "onResponse: " + response.body().string());
                }
            });
        }
    
    call.enqueue():
    @Override public void enqueue(Callback responseCallback) {
        synchronized (this) {
        //call是否被执行过
          if (executed) throw new IllegalStateException("Already Executed");
          executed = true;
        }
        captureCallStackTrace();
        eventListener.callStart(this);
        client.dispatcher().enqueue(new AsyncCall(responseCallback));
      }
    
    client.dispatcher()
    //在public class OkHttpClient类下
      public Dispatcher dispatcher() {
        return dispatcher; //dispatcher在OkHttpClient的Builder()的时候已经初始化
      }
    
    client.dispatcher().enqueue
      synchronized void enqueue(AsyncCall call) {
        if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
          runningAsyncCalls.add(call);
          executorService().execute(call);
        } else {
          readyAsyncCalls.add(call);
        }
      }
    

    enqueue()总结:
    1.判断当前call是否执行过;
    2.把传过来等call封装成一个AsyncCall对象,AsyncCall其实就是一个runnable
    3.client.dispatcher().enqueue()进行异步请求:当正在请求当runnable个数小于64并且当前网络请求当host小于5个请求当时候,这时会把runnable放到请求异步队列当中,然后通过线程池去执行call的请求。如果不是,会把runnable添加到等待就绪当异步请求队列当中。

    线程池执行call请求
    @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 {
              eventListener.callFailed(RealCall.this, e);
              responseCallback.onFailure(RealCall.this, e);
            }
          } finally {
            client.dispatcher().finished(this);
          }
        }
    

    判断请求重定向(retryAndFollowUpInterceptor)是否被取消,如果被取消,回调onFailure;如果没有被取消,回调onResponse。最后调用client.dispatcher().finished(this)

    client.dispatcher().finished(this)
      void finished(AsyncCall call) {
        finished(runningAsyncCalls, call, true);
      }
    
      private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
        int runningCallsCount;
        Runnable idleCallback;
        synchronized (this) {
          //把当前的call从运行的runnable里移除
          if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
        //调整正在异步请求的队列,把待请求的call加入进去
          if (promoteCalls) promoteCalls();
          //重新计算正在请求的线程数
          runningCallsCount = runningCallsCount();
          idleCallback = this.idleCallback;
        }
        if (runningCallsCount == 0 && idleCallback != null) {
          idleCallback.run();
        }
      }
    

    okhttp的任务调度

    okhttp如何实现同步和异步请求?

    发送的同步/异步请求都会在dispatcher中管理其状态

    dispatcher的作用

    维护请求的状态,维护一个线程池,用于执行请求。

    public final class Dispatcher {
    ···
    //维护了一个异步高效的线程池来执行网络操作
      private @Nullable ExecutorService executorService;
    //就绪状态的异步请求状态
      private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();
    //正在执行的的异步请求,包含:已经取消,但是没有执行完的请求
      private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();
    
      private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
    }
    

    okhttp的拦截器

    相关文章

      网友评论

          本文标题:Okhttp原理

          本文链接:https://www.haomeiwen.com/subject/neclbctx.html