OkHttp流程分析,基于android的app的设计与开发

public 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.java
Call newCall(Request request) {
//此处传入我们的OkHttpClient
return RealCall.newRealCall(this, request, false);
}

//RealCall.java
RealCall 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中获取其中的Dispatcher
client.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 executableCalls = new ArrayList<>();
boolean isRunning;
synchronized (this) {
//循环收集可以执行的AsyncCall
for (Iterator 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.execute
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);
}
}
}

到了这里我们的AsyncCall就顺利执行了。整个Okhttp代码的主干就在这里。接下来我们继续探讨okhttp这个框架的一些细节设计

拦截器链

前边得到Response的地方,我们调用了getResponseWithInterceptorChain()。但没细讲,这个部分就是大名鼎鼎的okhttp的拦截器链。

//RealCall.java

}

到了这里我们的AsyncCall就顺利执行了。整个Okhttp代码的主干就在这里。接下来我们继续探讨okhttp这个框架的一些细节设计

拦截器链

前边得到Response的地方,我们调用了getResponseWithInterceptorChain()。但没细讲,这个部分就是大名鼎鼎的okhttp的拦截器链。

//RealCall.java

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值