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() {@Overridepublic void onFailure(Call call, IOException e) {Log.d(TAG, "onFailure: ");}
@Overridepublic void onResponse(Call call, Response response) throws IOException {Log.d(TAG, "onResponse: " + response.body().string());}});
在上述代码中可以看到几个关键类和作用
OkHttpClient : 用于创建 Call 对象,源码注释是 Factory for {@linkplain Call calls}
Request :构建我们的请求。源码注释是 An HTTP request。简单直接
Call :发起我们的 http 请求
开始分析
OkHttpClient 和 Request
先看看我们的 OkHttpClient Request
OkHttpClient.java
public OkHttpClient() {this(new Builder());}
我们跟进代码可以看到 OkHttpClient 是一个构建者模式。Request 不跟进也可以看到是一个构造者模式。
接下来,我们继续看 Call
Call
//OkHttpClient.javaCall newCall(Request request) {//此处传入我们的 OkHttpClientreturn RealCall.newRealCall(this, request, false);}
//RealCall.javaRealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {RealCall call = new RealCall(client, originalRequest, forWebSocket);//Transmitter 意为发射器,功能挺杂。注释说是 OkHttp 的应用程序和网络层之间的桥梁 call.transmitter = new Transmitter(client, call);return call;}
在这段代码中,我们可以看到我们得到的 Call 的实例是 RealCall。所以我们 enqueue()方法的调用实际是 RealCall 的方法。
@Override public void enqueue(Callback responseCallback) {synchronized (this) {if (executed) throw new IllegalStateException("Already Executed");executed = true;}transmitter.callStart();//从我们之前传入 OkHttpClient 中获取其中的 Dispatcherclient.dispatcher().enqueue(new AsyncCall(responseCallback));}
注意这里有一个 Dispatcher。这个类负责我们网络请求的调度策略。在这段代码中我们用 AsyncCall 封装了我们的 Callback。AsyncCall 是一个 NamedRunnable。在这个 NamedRunnable 中封装了我们的 execute()
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();}
execute()的具体实现如下
@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);}}
在上面这个方法中我们可以看到请求的结果是如何获得,那么这个 runnable 任务是怎么调度执行的呢?我们就得回过头看看 Dispatcher 类的 enqueue()方法做了啥
void enqueue(AsyncCall call) {synchronized (this) {readyAsyncCalls.add(call);
if (!call.get().forWebSocket) {//如果有请求同一 host 的 AsyncCall 就进行复用 AsyncCall existingCall = findExistingCallWithHost(call.host());if (existingCall != null) call.reuseCallsPerHostFrom(existingCall);}}推动执行方法 promoteAndExecute();}
private boolean promoteAndExecute() {assert (!Thread.holdsLock(this));
List<AsyncCall> executableCalls = new ArrayList<>();boolean isRunning;synchronized (this) {//循环收集可以执行的 AsyncCallfor (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {AsyncCall asyncCall = i.next();
if (runningAsyncCalls.size() >= maxRequests) break; // 最大执行的 call 大于 64 跳出 if (asyncCall.callsPerHost().get() >= maxRequestsPerHost) continue; // 请求同一 host 的 call > 5 跳过
i.remove();asyncCall.callsPerHost().incrementAndGet();executableCalls.add(asyncCall);runningAsyncCalls.add(asyncCall);}isRunning = runningCallsCount() > 0;}
//把可以执行的 AsyncCall,统统执行 for (int i = 0, size = executableCalls.size(); i < size; i++) {AsyncCall asyncCall = executableCalls.get(i);//executorService()返回一个线程池 asyncCall.executeOn(executorService());}
return isRunning;}
void executeOn(ExecutorService executorService) {boolean success = false;try {//线程池运行 Runnable,执行 run,调用前面提到的 AsyncCall.executeexecutorService.execute(this);success = true;} catch (RejectedExecutionException e) {InterruptedIOException ioException = new InterruptedIOException("executor rejected");ioException.initCause(e);transmitter.noMoreExchanges(ioException);//失败回调
评论