okhttp源码的简单分析

okhttp是一个非常好用的开源的网络请求框架,接下来我们就来简单分析一下okhttp的源码。

首先我们来大致看一下同步方法的使用,在这里我们以get方式为例

    public static String get(String url, String json){
        OkHttpClient okHttpClient=new OkHttpClient();
        Request request = new Request.Builder()
                          .url(url)
                          .build();
        Response response = null;
        try {
            response = okHttpClient
                       .newCall(request)
                       .execute();
            if (response.isSuccessful()) {
               return response.body().string();
            }
        } catch (IOException e) {
            Log.i("tag",e.getMessage());
            e.printStackTrace();
        }
        return "{'error':'错误'}";
    }

我们首先创建了一个okHttpClient,然后又封装了Request请求,最后调用了okHttpClient的newCall(request).exexute()方法。这样就简单完成了一次访问服务器的请求。那么它内部到底是如何操作的呢?接下来我们就来分析一下源码。

    public Call newCall(Request request) {
        return new Call(this, request);
    }
    protected Call(OkHttpClient client, Request originalRequest){
        this.client = client.copyWithDefaults();
        this.originalRequest = originalRequest;
    }

    public Response execute() throws IOException {
        synchronized(this) {
            if(this.executed) {
                throw new IllegalStateException("Already Executed");
            }

            this.executed = true;
        }

        Response var2;
        try {
            this.client.getDispatcher().executed(this);
            Response result = this.getResponseWithInterceptorChain(false);
            if(result == null) {
                throw new IOException("Canceled");
            }

            var2 = result;
        } finally {
            this.client.getDispatcher().finished(this);
        }

        return var2;
    }

下面我们就具体分析一下。
newCall()方法会最终调用Call类的构造函数new Call(),从而进行初始化。继而调用Call类的execute方法。在execute方法中,首先会先判断该请求是否已执行,若已执行,抛出异常,若没有执行则会调用Dispatcher.exexute()方法。Dispatcher就是一个分发器,它是okHttpClient的一个成员变量。下面是Dispatcher的成员变量的定义

private int maxRequests = 64;
private int maxRequestsPerHost = 5;
private ExecutorService executorService;
private final Deque<AsyncCall> readyCalls = new ArrayDeque();
private final Deque<AsyncCall> runningCalls = new ArrayDeque();
private final Deque<Call> executedCalls = new ArrayDeque();

Dispatcher类中使用了线程池,设置了最大的请求数等等

 public synchronized ExecutorService getExecutorService() {
     if(this.executorService == null) {
         this.executorService = new ThreadPoolExecutor(
         0, 
         214748364760L, 
         TimeUnit.SECONDS, 
         new SynchronousQueue(),                                     
         Util.threadFactory("OkHttp Dispatcher", false));
      }
      return this.executorService;
 }

由代码可以看出,这里创建了一个线程池,核心线程数为0,最大线程数为2147483647,空闲时间为60s。在这里就不具体讲解该线程池。
接着回到exexute方法中,dispatcher的exexute方法会将该call请求放入队列中

synchronized void executed(Call call) {
    this.executedCalls.add(call);
}

然后会调用getResponseWithInterceptorChain()方法,最后执行完毕会将请求从队列中移除,即 this.client.getDispatcher().finished(this);
接着我们具体分析getResponseWithInterceptorChain()方法,getResponseWithInterceptorChain是真正完成请求的方法。

private Response getResponseWithInterceptorChain(boolean forWebSocket) throws IOException {
        Call.ApplicationInterceptorChain chain = new Call.ApplicationInterceptorChain(0, this.originalRequest, forWebSocket);
        return chain.proceed(this.originalRequest);
    }
class ApplicationInterceptorChain implements Chain {
        private final int index;
        private final Request request;
        private final boolean forWebSocket;

        ApplicationInterceptorChain(int index, Request request, boolean forWebSocket) {
            this.index = index;
            this.request = request;
            this.forWebSocket = forWebSocket;
        }

        public Connection connection() {
            return null;
        }

        public Request request() {
            return this.request;
        }

        public Response proceed(Request request) throws IOException {
            if(this.index < Call.this.client.interceptors().size()) {
                Call.ApplicationInterceptorChain chain = Call.this.new ApplicationInterceptorChain(this.index + 1, request, this.forWebSocket);
                return ((Interceptor)Call.this.client.interceptors().get(this.index)).intercept(chain);
            } else {
                return Call.this.getResponse(request, this.forWebSocket);
            }
        }
    }

首先先创建一个拦截器对象链,然后调用其proceed方法。在proceed方法中,如果有拦截器,则会由拦截器依次处理,处理完毕以后调用getResponse()方法。getResponse方法中做了如下操作:将request封装成HttpEngine,由HttpEngine发送请求和接收回应,接收成功以后,释放链接,返回response
最后总结一下,okHttp的流程图
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值