Android开发Android开发经验谈Android开发

okHttp源码分析

2020-04-26  本文已影响0人  卖炭少年炭治郎

okhttp版本

基本使用

        String url = "http://wwww.baidu.com";
        OkHttpClient okHttpClient = new OkHttpClient();
        final Request request = new Request.Builder()
                .url(url)
                .get()//默认就是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());
            }
        });

源码分析

我们从调用的方式着手,看看代码是怎么走的

  1. 首先new OkHttpClient()这个对象,跟一下,看看构造方法里面干了什么?
 public OkHttpClient() {
    this(new Builder());
  }

在new Builder()里面初始化了一些信息

public Builder() {
    //这个是请求分发器,其实内部就是封装了线程池,但是new 里面是空实现
      dispatcher = new Dispatcher();
      //这个支持的协议 默认1.1 ,TLS1.2
      protocols = DEFAULT_PROTOCOLS;
      connectionSpecs = DEFAULT_CONNECTION_SPECS;
      //记录事件
      eventListenerFactory = EventListener.factory(EventListener.NONE);
      proxySelector = ProxySelector.getDefault();
      cookieJar = CookieJar.NO_COOKIES;
      socketFactory = SocketFactory.getDefault();
      hostnameVerifier = OkHostnameVerifier.INSTANCE;
      certificatePinner = CertificatePinner.DEFAULT;
      proxyAuthenticator = Authenticator.NONE;
      authenticator = Authenticator.NONE;
      //连接池 内部也是封装了线程池,不过线程池早就创建好了备用了
      connectionPool = new ConnectionPool();
      //域名解析
      dns = Dns.SYSTEM;
      followSslRedirects = true;
      followRedirects = true;
      retryOnConnectionFailure = true;
      connectTimeout = 10_000;
      readTimeout = 10_000;
      writeTimeout = 10_000;
      pingInterval = 0;
    }
  1. 然后需要创建一个Request对象,可以看到这个类里面只是对url,请求头信息的一些存储。
  2. 通过okHttpClient.newCall(request),创建一个call对象。跟踪代码发现里面就是new RealCall()对象出来,RealCall实现了Cal接口。
 @Override public Call newCall(Request request) {
    return RealCall.newRealCall(this, request, false /* for web socket */);
  }
static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    // Safely publish the Call instance to the EventListener.
    RealCall call = new RealCall(client, originalRequest, forWebSocket);
    call.eventListener = client.eventListenerFactory().create(call);
    return call;
  }
  1. 执行了call.enqueue()方法,就能拿到请求结果了。我们跟一下这个方法的实现
 @Override public void enqueue(Callback responseCallback) {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    eventListener.callStart(this);
    //最终会调用到分发器的enqueue方法
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }
synchronized void enqueue(AsyncCall call) {
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
    //加入到正在执行的队列里面
      runningAsyncCalls.add(call);
      //executorService()如果还没有创建线程池,就创建一个。执行这个runnable
      executorService().execute(call);
    } else {
    //如果超过最大请求个数,就放到准备队列里面
      readyAsyncCalls.add(call);
    }
  }
  1. client.dispatcher().enqueue(new AsyncCall(responseCallback)),我们看下AsyncCall的run方法干了什么?
    发现AsyncCall并没有run方法,跟到父类里面NamedRunnable发现是执行了execute()方法
 @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();

AsyncCall里面的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 {
          eventListener.callFailed(RealCall.this, e);
          responseCallback.onFailure(RealCall.this, e);
        }
      } finally {
        client.dispatcher().finished(this);
      }
    }
  }
  1. getResponseWithInterceptorChain()方法里干了什么呢?
    这就是okhttp的责任链机制,拦截,执行调用下个拦截,最终CallServerInterceptor里面实现网络请求拿到请求结果。
Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List<Interceptor> interceptors = new ArrayList<>();
    //这里先添加我们自定义的拦截器
    interceptors.addAll(client.interceptors());
    interceptors.add(retryAndFollowUpInterceptor);
    interceptors.add(new BridgeInterceptor(client.cookieJar()));
    interceptors.add(new CacheInterceptor(client.internalCache()));
    interceptors.add(new ConnectInterceptor(client));
    if (!forWebSocket) {
      interceptors.addAll(client.networkInterceptors());
    }
    interceptors.add(new CallServerInterceptor(forWebSocket));

    Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
        originalRequest, this, eventListener, client.connectTimeoutMillis(),
        client.readTimeoutMillis(), client.writeTimeoutMillis());
    return chain.proceed(originalRequest);
  }

我们也可以实现Interceptor接口,添加自己定义的拦截器,实现请求日志的打印。

上一篇 下一篇

猜你喜欢

热点阅读