OkHttp3源码--请求流程

作者: 若邪 | 来源:发表于2018-12-25 16:00 被阅读2次

    一、OkHttp3的使用

    流程:

    同步:

    Response response = client.newCall(request).execute();
    

    异步:

    client.newCall(request).enqueue(new Callback() {});
    
    1、创建OkHttpClient客户端

    a、

    OkHttpClient client = new OkHttpClient();
    

    b、

    OkHttpClient okHttpClient = new OkHttpClient.Builder()
        .addInterceptor(interceptor)
        .connectTimeout(TIMEOUT_CONNECTION, TimeUnit.SECONDS)
        .addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request()
                    .newBuilder()
                    .build();
                return chain.proceed(request);
            }
        })
        .build();
    
    2、创建Request请求体
    Request request = new Request.Builder()
        .url(url)
        .build();
    
    3、执行请求

    a、同步请求

    Response response = client.newCall(request).execute();
    

    b、异步请求

    client.newCall(request).enqueue(new Callback() {
        @Override 
        public void onFailure(Call call, IOException e) {
            e.printStackTrace();
        }
    
        @Override 
        public void onResponse(Call call, Response response) throws IOException {
            ...
        });
    

    二、OkHttp3请求流程

    1、创建OkHttpClient客户端;
    client...
    
    2、调用newCall方法添加请求体Request;
    client.newCall(request)...;
    
    3、newCall方法实际调用RealCall类的newRealCall方法;
    @Override 
    public Call newCall(Request request) {
        return RealCall.newRealCall(this, request, false /* for web socket */);
    }
    
    4、执行execute()或者enqueue()方法;
    5、拦截器处理;
    Response result = getResponseWithInterceptorChain();
    
    6、最后返回请求结果;

    三、源码分析

    1、创建OkHttpClient客户端
    OkHttpClient client = new OkHttpClient();
    

    OkHttpClient构造方法,默认通过Builder创建,此时参数均为默认

    public OkHttpClient() {
        this(new Builder());
    }
    

    Builder模式,初始化OkHttpClient参数

    public Builder() {
        dispatcher = new Dispatcher();
        protocols = DEFAULT_PROTOCOLS;
        ...
    }
    

    指定具体参数(非默认)时,调用该方法生效

    public OkHttpClient build() {
        return new OkHttpClient(this);
    }
    

    指定具体参数后调用该方法使其生效

    OkHttpClient(Builder builder) {
        this.dispatcher = builder.dispatcher;
        this.proxy = builder.proxy;
        ...
    }
    
    2、Request的创建
    Request request = new Request.Builder().url(url).build();
    

    创建方式同OkHttpClient,Builder模式

    public Builder() {
        this.method = "GET";
        this.headers = new Headers.Builder();
    }
    Builder(Request request) {
        this.url = request.url;
        this.method = request.method;
        ...
    }
    public Request build() {
        if (url == null) throw new IllegalStateException("url == null");
        return new Request(this);
    }
    Request(Builder builder) {
        this.url = builder.url;
        this.method = builder.method;
        ...
    }
    
    3、OkHttpClient的newCall方法
    Response response = client.newCall(request).xxx();
    

    这里的newCall方法具体执行的是RealCall类的newRealCall方法

    @Override public Call newCall(Request request) {
        return RealCall.newRealCall(this, request, false /* for web socket */);
    }
    

    真正创建call的地方

    static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
        // Safely publish the Call instance to the EventListener.
        RealCall call = new RealCall(client, originalRequest, forWebSocket);
        call.eventListener = client.eventListenerFactory().create(call);
        return call;
    }
    private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
        this.client = client;
        this.originalRequest = originalRequest;
        ...
    }
    
    4、同步请求execute()
    Response response = client.newCall(request).execute();
    

    上一步提到这里的Call具体实现是RealCall类(Call只是个接口),所以这里执行的是RealCall类的execute()方法;

    @Override 
    public Response execute() throws IOException {
        synchronized (this) {
            // 同步请求只执行一次,被标记为已经执行的不会再执行
            if (executed) throw new IllegalStateException("Already Executed");
            executed = true;
        }
        captureCallStackTrace();
        timeout.enter();
        eventListener.callStart(this);
        try {
            // 由dispatcher将请求放入同步请求队列,这里可以看到执行同步请求并不是立即执行,而是将其放入请求队列,由队列出维护
            client.dispatcher().executed(this);
            // 拦截器相关处理,最终返回请求结果
            Response result = getResponseWithInterceptorChain();
            if (result == null) throw new IOException("Canceled");
            return result;
        } catch (IOException e) {
            e = timeoutExit(e);
            eventListener.callFailed(this, e);
            throw e;
        } finally {
            // 最终由dispatcher将请求移出请求同步请求队列
            client.dispatcher().finished(this);
        }
    }
    

    添加拦截器,并调用RealInterceptorChain类的proceed方法

    Response getResponseWithInterceptorChain() throws IOException {
        ...
        Interceptor.Chain chain = new RealInterceptorChain(interceptors,null,null, null,0,originalRequest,this,eventListener,client.connectTimeoutMillis(),client.readTimeoutMillis(), client.writeTimeoutMillis());    
        return chain.proceed(originalRequest);
    }
    

    RealInterceptorChain # proceed

    @Override 
    public Response proceed(Request request) throws IOException {
    return proceed(request, streamAllocation, httpCodec, connection);
    }
    

    真正执行的方法

    public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec, RealConnection connection) throws IOException {
        ...
        // 实例化下一个拦截器的Chain对象
        RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec, connection, index + 1, request, call, eventListener, connectTimeout, readTimeout, writeTimeout);
        // 拿到当前的拦截器
        Interceptor interceptor = interceptors.get(index);
        // 调用当前拦截器的intercept方法,并将下一个拦截器的Chain对象传递,直到最后得到response
        Response response = interceptor.intercept(next);
        ...
        if (response.body() == null) {
            throw new IllegalStateException("interceptor " + interceptor + " returned a response with no body");
        }
        return response;
    }
    
    5、异步请求enqueue()
     Response response = client.newCall(request).enqueue();
    

    Call的具体实现类RealCall中:

    @Override 
    public void enqueue(Callback responseCallback) {
        // 同理,执行情况标记
        synchronized (this) {
            if (executed) throw new IllegalStateException("Already Executed");
            executed = true;
        }
        captureCallStackTrace();
        eventListener.callStart(this);
        // 执行Dispatcher的enqueue()方法,将一个异步请求放入异步请求队列
        client.dispatcher().enqueue(new AsyncCall(responseCallback));
    }
    

    Dispatcher# enqueue():

    void enqueue(AsyncCall call) {
        synchronized (this) {
        // 放入准备异步请求队列
        readyAsyncCalls.add(call);
    }
        promoteAndExecute();
    }
    

    Dispatcher# promoteAndExecute():

    private boolean promoteAndExecute() {
        assert (!Thread.holdsLock(this));
        List<AsyncCall> executableCalls = new ArrayList<>();
        boolean isRunning;
        synchronized (this) {
        // 逐个从异步请求队列中取出请求
        for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
            AsyncCall asyncCall = i.next();
            // 正在运行的队列是否已经达到最大数
            if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity.
            // call占用的host小于最大数量
            if (runningCallsForHost(asyncCall) >= maxRequestsPerHost) continue; // Host max capacity.
    i.remove();
            // 将请求添加到可执行队列
            executableCalls.add(asyncCall);
            // 将请求添加到正在执行的队列
            runningAsyncCalls.add(asyncCall);
        }
            isRunning = runningCallsCount() > 0;
        }
        for (int i = 0, size = executableCalls.size(); i < size; i++) {
            AsyncCall asyncCall = executableCalls.get(i);
            // 创建一个线程池,由RealCall中的AsyncCall去执行
            asyncCall.executeOn(executorService());
        }
        return isRunning;
    }
    

    AsyncCall类

    final class AsyncCall extends NamedRunnable {
        ...
        void executeOn(ExecutorService executorService) {
            assert (!Thread.holdsLock(client.dispatcher()));
            boolean success = false;
            try {
                // 由线程池去具体执行异步请求
                executorService.execute(this);
                success = true;
            } catch (RejectedExecutionException e) {
                InterruptedIOException ioException = new InterruptedIOException("executor rejected");
                ioException.initCause(e);
                eventListener.callFailed(RealCall.this, ioException);
                responseCallback.onFailure(RealCall.this, ioException);
            } finally {
                if (!success) {
                    client.dispatcher().finished(this); // This call is no longer running!
                }
            }
    }
    

    最终执行到这里

    @Override 
    protected void execute() {
        boolean signalledCallback = false;
        timeout.enter();
        try {
            // 拦截器相关处理
            Response response = getResponseWithInterceptorChain();
            if (retryAndFollowUpInterceptor.isCanceled()) {
                signalledCallback = true;
                responseCallback.onFailure(RealCall.this,new IOException("Canceled"));
            } else {
                signalledCallback = true;
                responseCallback.onResponse(RealCall.this, response);
            }
        } catch (IOException e) {
            e = timeoutExit(e);
            if (signalledCallback) {
            // Do not signal the callback twice!
            Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
            } else {
                eventListener.callFailed(RealCall.this, e);
                responseCallback.onFailure(RealCall.this, e);
            }
        } finally {
            client.dispatcher().finished(this);
        }
    }
    
    6、拦截器处理

    拦截器处理相关代码

    Response getResponseWithInterceptorChain() throws IOException {
        // Build a full stack of interceptors.
        List<Interceptor> interceptors = new ArrayList<>();
        // 将创建OkHttpClient对象时设置的拦截器添加进来
        interceptors.addAll(client.interceptors());
        // 失败重试及重定向,该对象在RealCall构造方法中初始化
        interceptors.add(retryAndFollowUpInterceptor);
        // 请求时添加必要的Header信息,获取响应时移除必要的Header
        interceptors.add(new BridgeInterceptor(client.cookieJar()));
        // 缓存相关的拦截器
        interceptors.add(new CacheInterceptor(client.internalCache()));
        // 网络连接,和服务器连接
        interceptors.add(new ConnectInterceptor(client));
        if (!forWebSocket) {
        // 配置 OkHttpClient 时设置的 networkInterceptors
            interceptors.addAll(client.networkInterceptors());
        }
        // 负责向服务器发送请求数据、从服务器读取响应数据
        interceptors.add(new CallServerInterceptor(forWebSocket));
        Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0, originalRequest, this, eventListener, client.connectTimeoutMillis(), client.readTimeoutMillis(), client.writeTimeoutMillis());
    return chain.proceed(originalRequest);
    }
    

    相关文章

      网友评论

        本文标题:OkHttp3源码--请求流程

        本文链接:https://www.haomeiwen.com/subject/pnpflqtx.html