写点什么

OkHttp 流程分析,音视频编解码技术

用户头像
Android架构
关注
发布于: 2021 年 11 月 05 日

==========


在分析之前,先写一段没有任何封装的请求代码


String url = "http://wwww.baidu.com";OkHttpClient okHttpClient =


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


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);//失败回调

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
OkHttp流程分析,音视频编解码技术