源码分析之——OKHttp

1.源码分析之——AMS启动流程
2.源码分析之——WMS启动流程
3.源码分析之——SharedPreferences
4.源码分析之——Retrofit
5.源码分析之——OKHttp
6.源码分析之——Android事件分发机制

在这里插入图片描述

前言

基于源码,简单分析下OKHttp工作流程。

流程图

在这里插入图片描述

OKHttp基本使用

在 gradle 中添加依赖

implementation 'com.squareup.okhttp3:okhttp:3.14.9'

1.首先创建OkHttpClient对象

OkHttpClient client = new OkHttpClient();

2.构造Request对象

Request request = new Request.Builder()
                .get()
                .url("https://www.baidu.com")
                .build();

3.将Request封装为Call

Call call = client.newCall(request);

4.根据需要调用同步或者异步请求方法

//同步调用,返回Response,会抛出IO异常
Response response = call.execute();
//异步调用,并设置回调函数
call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
            }

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

源码分析

下面将从源码角度对以上流程进行分析。OKHttp使用建造者模式进行创建,因此让我们从Builder开启源码分析之旅吧。注意:为了精简内容,部分不在分析之内的代码已省略,如果想深入学习的同学请查看详细源码,本文基于OKHttp3.14.9版本。
OKHttp源码

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

这里使用建造者模式,我们直接看Builder即可

    public Builder() {
      dispatcher = new Dispatcher();
      protocols = DEFAULT_PROTOCOLS;
      ...
      readTimeout = 10_000;
      writeTimeout = 10_000;
      pingInterval = 0;
    }

这里直接初始化若干参数,直接跳过

 public OkHttpClient build() {
      return new OkHttpClient(this);
    }

到这里OkHttpClient已经创建成功。下面是先创建一个Request对象,这个我们就不看了,我们来看下newCall方法。

  @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.transmitter = new Transmitter(client, call);
    return call;
  }

看来这边创建了一个真实的RealCall对象并return该对象。获取到RealCall对象后,可以根据需求调用同步execute()或者异步enqueue(),前者比较简单在此不做分析,我们主要讨论下异步enqueue()的后续实现。

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

原来调用了Dispatcher下的enqueue()方法,跟踪下去看下。

    void enqueue(AsyncCall call) {
        synchronized (this) {
            readyAsyncCalls.add(call);

            // Mutate the AsyncCall so that it shares the AtomicInteger of an existing running call to
            // the same host.
            if (!call.get().forWebSocket) {
                AsyncCall existingCall = findExistingCallWithHost(call.host());
                if (existingCall != null) call.reuseCallsPerHostFrom(existingCall);
            }
        }
        promoteAndExecute();
    }

先将call添加至待执行对象中,然后跳转至promoteAndExecute()

    private boolean promoteAndExecute() {
        assert (!Thread.holdsLock(this));

        List<AsyncCall> executableCalls = new ArrayList<>();
        boolean isRunning;
        synchronized (this) {
            for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
                AsyncCall asyncCall = i.next();

                if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity.
                if (asyncCall.callsPerHost().get() >= maxRequestsPerHost) continue; // Host max capacity.

                i.remove();
                asyncCall.callsPerHost().incrementAndGet();
                executableCalls.add(asyncCall);
                runningAsyncCalls.add(asyncCall);
            }
            isRunning = runningCallsCount() > 0;
        }

        for (int i = 0, size = executableCalls.size(); i < size; i++) {
            AsyncCall asyncCall = executableCalls.get(i);
            asyncCall.executeOn(executorService());
        }

        return isRunning;
    }

可以看到该方法表示正在执行了,先将call添加到running队列中,然后for循环挨个执行asyncCall.executeOn(),注意这边执行是异步放在线程池中的。

 void executeOn(ExecutorService executorService) {
            assert (!Thread.holdsLock(client.dispatcher()));
            boolean success = false;
            try {
                executorService.execute(this);
                success = true;
            } catch (RejectedExecutionException e) {
                InterruptedIOException ioException = new InterruptedIOException("executor rejected");
                ioException.initCause(e);
                transmitter.noMoreExchanges(ioException);
                responseCallback.onFailure(RealCall.this, ioException);
            } finally {
                if (!success) {
                    client.dispatcher().finished(this); // This call is no longer running!
                }
            }
        }

注意看executorService.execute(this),貌似一看这啥意思啊,突然冒出来这么一句。。。不急,保存冷静。

final class AsyncCall extends NamedRunnable {
}

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();
}

奥奥,一下子眼前一亮,原来是继承了NamedRunnable ,最终还是走到了execute()。至此,Request部分已经讲完了,下面就看Response了。

@Override
        protected void execute() {
            boolean signalledCallback = false;
            transmitter.timeoutEnter();
            try {
                Response response = getResponseWithInterceptorChain();
                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);
                }
            } catch (Throwable t) {
                cancel();
                if (!signalledCallback) {
                    IOException canceledException = new IOException("canceled due to " + t);
                    canceledException.addSuppressed(t);
                    responseCallback.onFailure(RealCall.this, canceledException);
                }
                throw t;
            } finally {
                client.dispatcher().finished(this);
            }
        }

获取Response为getResponseWithInterceptorChain()方法,跟踪下去看

Response getResponseWithInterceptorChain() throws IOException {
        // Build a full stack of interceptors.
        List<Interceptor> interceptors = new ArrayList<>();
        interceptors.addAll(client.interceptors());
        interceptors.add(new RetryAndFollowUpInterceptor(client));
        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, transmitter, null, 0,
                originalRequest, this, client.connectTimeoutMillis(),
                client.readTimeoutMillis(), client.writeTimeoutMillis());

        boolean calledNoMoreExchanges = false;
        try {
            Response response = chain.proceed(originalRequest);
            if (transmitter.isCanceled()) {
                closeQuietly(response);
                throw new IOException("Canceled");
            }
            return response;
        } catch (IOException e) {
            calledNoMoreExchanges = true;
            throw transmitter.noMoreExchanges(e);
        } finally {
            if (!calledNoMoreExchanges) {
                transmitter.noMoreExchanges(null);
            }
        }
    }

先添加了若干个拦截器,然后调用chain.proceed(originalRequest)。

 public Response proceed(Request request, Transmitter transmitter, @Nullable Exchange exchange)
      throws IOException {
    if (index >= interceptors.size()) throw new AssertionError();

    calls++;
    ...
    // Call the next interceptor in the chain.
    RealInterceptorChain next = new RealInterceptorChain(interceptors, transmitter, exchange,
        index + 1, request, call, connectTimeout, readTimeout, writeTimeout);
    Interceptor interceptor = interceptors.get(index);
    Response response = interceptor.intercept(next);
    ...
    return response;
  }

然后看一下interceptor.intercept(next)是怎么实现的

 @Override
    public Response intercept(Chain chain) throws IOException {
        RealInterceptorChain realChain = (RealInterceptorChain) chain;
        Request request = realChain.request();
        Transmitter transmitter = realChain.transmitter();

        // We need the network to satisfy this request. Possibly for validating a conditional GET.
        boolean doExtensiveHealthChecks = !request.method().equals("GET");
        Exchange exchange = transmitter.newExchange(chain, doExtensiveHealthChecks);

        return realChain.proceed(request, transmitter, exchange);
    }

可以看到方法里面又调用realChain.proceed(),然后每次calls++,index+1,不断new一个RealInterceptorChain的next对象,这不是在使用递归嘛,通过递归的思想将所有拦截器执行完毕,最终返回一个response.。这里利用递归循环,也被称为责任链模式

到这里OkHttp的流程基本上分析完了,记录学习心得,感谢留言交流,共同学习。

在这里插入图片描述

评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值