OKHttp分发器源码分析(两个版本)

文章目录

    • 【1】简介
    • 【2】简单使用(略谈)
      • ①使用流程图如下:
      • ②使用代码如下:
    • 【3】分发器(两个版本)
      • 一、OKHttp 3.10.0版本的分发器源码追溯
      • 二、OKHttp4.9.3版本的源码分析
      • 三、两个不同版本的执行流程比较:
        • ①3.10.0版本的流程
        • ②4.9.3版本的流程
      • 四、分发器中的线程池

【1】简介

OkHttp是当下Android使用最频繁的网络请求框架,由Square公司开源。 Google在Android4.4以后开始将源码中的HttpURLConnection底层实现替换为0KHttp,同时现在流行的Retrofit框架底层同样是使用OKHttp的。

我们将了解下OKHttp的源码,但是不同的版本源码会有一些差异,等下我会大概说一下3.10.04.9.3版本的不同之处


【2】简单使用(略谈)

大家应该都用过OKHttp,只是你们自己可能都不知道,因为我们项目中经常使用的是像Retrofit这样的网络框架,但其实Retrofit是基于OKHttp进行的再次封装,将返回的结果等进行了一些更加人性化的封装,更便于我们开发使用。

①使用流程图如下:

OKHttp分发器源码分析(两个版本)_第1张图片

②使用代码如下:

//1
        OkHttpClient okHttpClient = new OkHttpClient();
        
        //2
        Request request = new Request.Builder()
                .url("www.baidu.com")
                .build();
        //3
        Call call = okHttpClient.newCall(request);
        
        //4异步请求
        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NonNull Call call, @NonNull IOException e) {

            }

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

            }
        });
        
        //或者同步请求
        try {
            Response response = call.execute();
        } catch (IOException e) {
            e.printStackTrace();
        }

其实看了这个发现OKHttp重要的还是分发器和拦截器,那么下面我们就来讲一下什么是分发器、拦截器,他们有什么用,是怎么工作的。


【3】分发器(两个版本)

Dispatcher 分发器就是来调配请求任务的,内部会包含一个线程池(异步任务才会用到)。可以在创建 OkHttpClient 时,传递我们 自己定义的线程池来创建分发器。下面我们跟着源码追一下吧,我们看异步的,同步的可以自行查看比较简单。

一、OKHttp 3.10.0版本的分发器源码追溯

①从这里进去
OKHttp分发器源码分析(两个版本)_第2张图片
②Call只有一个默认实现类RealCall
OKHttp分发器源码分析(两个版本)_第3张图片

③进到RealCallenqueue中,发现要去到dispatcherenqueue
OKHttp分发器源码分析(两个版本)_第4张图片

④分发器中的enqueue
OKHttp分发器源码分析(两个版本)_第5张图片
分发器异步任务的时候有两个队列

  • runningAsyncCalls
  • readyAsyncCalls

running当前任务数小于规定的max值(默认64)(考虑到手机压力)
running队列里面正在访问的host和当前host相同的任务不能超过5个(减少服务器压力)

当正在执行的任务未超过最大限制64,同时 runningCallsForHost(call) < maxRequestsPerHost 同一Host的请求 不超过5个,则会添加到正在执行队列,同时提交给线程池直接执行。否则先加入等待队列。

⑤线程池执行应该是找到AsyncCall的run方法
OKHttp分发器源码分析(两个版本)_第6张图片

但他没有run方法,而且继承的也不是Runable对象,我们看下NamedRunnable到底是个什么东西


OKHttp分发器源码分析(两个版本)_第7张图片
原来如此,有个抽象的execute方法在run里面执行,所以线程池就会执行AsyncCallexecute方法了


OKHttp分发器源码分析(两个版本)_第8张图片
try和catch先不管看到finally,会执行finished方法


OKHttp分发器源码分析(两个版本)_第9张图片
将这个任务从runningAsyncCalls中移除,然后命中if语句,进入promoteCalls


OKHttp分发器源码分析(两个版本)_第10张图片
遍历readyAsyncCalls中的任务,根据判断的规则将任务加入到runningAsyncCalls中然后调用线程池进行执行。

现在我们想想是不是分发器我们已经走完一遍了?不是要从分发器到拦截器吗?根据我们上面的整体流程图应该是这样的,那我们什么时候进入到拦截器的呢?其实是在execute方法的时候:

OKHttp分发器源码分析(两个版本)_第11张图片

二、OKHttp4.9.3版本的源码分析


OKHttp分发器源码分析(两个版本)_第12张图片

②又是这个接口还是只有RealCall这个默认实现类
OKHttp分发器源码分析(两个版本)_第13张图片

③进入到RealCallenqueue
在这里插入图片描述

④来到dispatcherenqueue方法中
OKHttp分发器源码分析(两个版本)_第14张图片
这里已经是不一样的了,这里不再判断,而是直接将任务加入到readyAsyncCalls中,然后调用promoteAndExecute

OKHttp分发器源码分析(两个版本)_第15张图片
遍历,然后根据上面相同的条件,是否将任务加入到runningAsyncCalls中,另外多了一个队列executableCalls

OKHttp分发器源码分析(两个版本)_第16张图片
然后遍历执行executableCalls队列中的任务

OKHttp分发器源码分析(两个版本)_第17张图片
⑨还是要来到dispatcherfinished方法
OKHttp分发器源码分析(两个版本)_第18张图片

这个版本的源码我没有详细讲解,但是你们应该都看得懂。跟3.10.0版本的有一些区别,但是也有很多相似的地方

三、两个不同版本的执行流程比较:

①3.10.0版本的流程

OKHttp分发器源码分析(两个版本)_第19张图片

②4.9.3版本的流程

OKHttp分发器源码分析(两个版本)_第20张图片

四、分发器中的线程池

这里由于篇幅,不再详细说明,这里线程池的队列用的无界队列SynchronousQueue
在这里插入图片描述
核心线程数为0,最大线程数为Integer.MAX_VALUE
实现了一个最大并发量的线程池

你可能感兴趣的:(第三方框架,Android,android,java,android,studio)