OkHttp源码流程分析

OkHttp是有Square公司贡献一个处理网络请求的开源项目,是目前Android使用最广泛的网络框架,从Android4.4开始HttpURLConnection的底层也是采用Okhttp框架。

  • 支持HTTP/2并允许对同一主机的所有请求共享一个套接字
  • 通过连接池,减少了请求延迟
  • 默认通过GZip压缩数据
  • 响应缓存,避免重复请求网路
  • 请求失败自动重试主机的其他Host-IP地址,自动重定向

请求流程

  1. 一次完整的请求时,必须使用其中的三个对象分别为:OkHttpClient,Request,Call

  2. OkHttpClientRequest的创建可以使用提供的Builder(建造者模式)

  3. Call则是把Request交给OkHttpClient之后,返回的一个准备完整并且待执行的请求体

  4. 选择 execute同步/enqueue异步

    1. 如果是execute同步,返回Response 响应对象,需要注意的是这里有会存在线程阻塞,需抛出throws IOException
    2. 选择是enqueue异步,返回Callback接口并且实现- onFailure(Call call, IOException e)onResponse(Call call, Response response)
  5. Dispatcher 分发起Interceptors拦截器 是Okhttp的核心设计

  6. 通过 Response 响应对象,进行解析拿取数据集

请求流程图

okHttp请求流程图

事例代码


        String url = "http://wwww.xxxxx.com";

        //1.构造OkHttpClient对象
        OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
//                .cache()  缓存设置
//                .addInterceptor()  拦截器  
//                .sslSocketFactory()  SSL设置
                .build();

        //2.构造Request对象
        Request request = new Request.Builder()
                .url(url)
//                .post(new RequestBody())        Post请求体需要 RequestBody对象
                .build();

        //3.通过newCall返回请求
        Call call = okHttpClient.newCall(request);

        //4 - 1 同步请求
        Response response = call.execute();

        //4 - 2 异步请求
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.d(TAG, "onFailure: ");
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Log.d(TAG, "onResponse: " + response.body().string());
            }
        });

OkHttpClient

//默认建造 ... 等功能配置
    Builder() {
        dispatcher = new Dispatcher();
        protocols = DEFAULT_PROTOCOLS;
        connectionSpecs = DEFAULT_CONNECTION_SPECS;
        eventListenerFactory = EventListener.factory(EventListener.NONE);
        proxySelector = ProxySelector.getDefault();
        cookieJar = CookieJar.NO_COOKIES;
        socketFactory = SocketFactory.getDefault();
        hostnameVerifier = OkHostnameVerifier.INSTANCE;
        certificatePinner = CertificatePinner.DEFAULT;
        proxyAuthenticator = Authenticator.NONE;
        authenticator = Authenticator.NONE;
        connectionPool = new ConnectionPool();
        dns = Dns.SYSTEM;
        followSslRedirects = true;
        followRedirects = true;
        retryOnConnectionFailure = true;
        connectTimeout = 10_000;
        readTimeout = 10_000;
        writeTimeout = 10_000;
        pingInterval = 0;
    }

//配置构造
    Builder(OkHttpClient okHttpClient) {
        this.dispatcher = okHttpClient.dispatcher;  //分发器
        this.proxy = okHttpClient.proxy;        //代理
        this.protocols = okHttpClient.protocols;    
        this.connectionSpecs = okHttpClient.connectionSpecs;
        this.interceptors.addAll(okHttpClient.interceptors);    //拦截器
        this.networkInterceptors.addAll(okHttpClient.networkInterceptors);
        this.eventListenerFactory = okHttpClient.eventListenerFactory;
        this.proxySelector = okHttpClient.proxySelector;
        this.cookieJar = okHttpClient.cookieJar;    //cookie
        this.internalCache = okHttpClient.internalCache;
        this.cache = okHttpClient.cache;    //缓存
        this.socketFactory = okHttpClient.socketFactory;    //Socket配置
        this.sslSocketFactory = okHttpClient.sslSocketFactory;//SSL/TLS
        this.certificateChainCleaner = okHttpClient.certificateChainCleaner;
        this.hostnameVerifier = okHttpClient.hostnameVerifier;
        this.certificatePinner = okHttpClient.certificatePinner;
        this.proxyAuthenticator = okHttpClient.proxyAuthenticator;
        this.authenticator = okHttpClient.authenticator;
        this.connectionPool = okHttpClient.connectionPool;
        this.dns = okHttpClient.dns;
        this.followSslRedirects = okHttpClient.followSslRedirects;
        this.followRedirects = okHttpClient.followRedirects;
        this.retryOnConnectionFailure = okHttpClient.retryOnConnectionFailure;
        this.connectTimeout = okHttpClient.connectTimeout;  //连接超时
        this.readTimeout = okHttpClient.readTimeout;    //传递数据的超时
        this.writeTimeout = okHttpClient.writeTimeout;  //读取数据的超时
        this.pingInterval = okHttpClient.pingInterval; //心跳ping 
    }

Request

public static class Builder {
  HttpUrl url;
  String method;
  Headers.Builder headers;  
  RequestBody body;    //post请求体
  Object tag;

  public Builder() {
    this.method = "GET";
    this.headers = new Headers.Builder();
  }

  Builder(Request request) {
    this.url = request.url;
    this.method = request.method;
    this.body = request.body;
    this.tag = request.tag;
    this.headers = request.headers.newBuilder();
  }
  
  //.....
}

Call

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


static RealCall newRealCall(OkHttpClient client, Request originalRequest,boolean forWebSocket) {
    // 直接new出Call的实现对象RealCall
    RealCall call = new RealCall(client, originalRequest, forWebSocket);
    call.eventListener = client.eventListenerFactory().create(call);
    return call;
}
Call接口
package okhttp3;

import java.io.IOException;

//Call接口
public interface Call extends Cloneable {

  Request request();

  Response execute() throws IOException;

  void enqueue(Callback responseCallback);

  void cancel();

  boolean isExecuted();

  boolean isCanceled();


  Call clone();

  interface Factory {
    Call newCall(Request request);
  }
}

RealCall

final class RealCall implements Call {
   //....

    //同步请求
    @Override
    public Response execute() throws IOException {
        //call只能执行一个请求
        synchronized (this) {
            if (executed) throw new IllegalStateException("Already Executed");
            executed = true;
        }
        captureCallStackTrace();
        eventListener.callStart(this);
        try {
            //分发器 
            client.dispatcher().executed(this);
            //拦截器(完成请求封装U回调) =》得到结果响应
            Response result = getResponseWithInterceptorChain();
            if (result == null) throw new IOException("Canceled");
            return result;
        } catch (IOException e) {
            eventListener.callFailed(this, e);
            throw e;
        } finally {
            //回调通知
            client.dispatcher().finished(this);
        }
    }



    @Override
    public void enqueue(Callback responseCallback) {
        synchronized (this) {
            if (executed) throw new IllegalStateException("Already Executed");
            executed = true;
        }
        captureCallStackTrace();
        eventListener.callStart(this);
        //分发器
        client.dispatcher().enqueue(new AsyncCall(responseCallback));
    }

  

    //一个请求任务, 其NamedRunnable类实现Runnable接口,是一个模版设计模式
    final class AsyncCall extends NamedRunnable {
        private final Callback responseCallback;
        
        //接口回调
        AsyncCall(Callback responseCallback) {
            super("OkHttp %s", redactedUrl());
            this.responseCallback = responseCallback;
        }

        String host() {
            return originalRequest.url().host();
        }

        Request request() {
            return originalRequest;
        }

        RealCall get() {
            return RealCall.this;
        }

        @Override
        protected void execute() {
            boolean signalledCallback = false;
            try {
                //拦截器(完成请求封装U回调) =》得到结果响应
                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) {
                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 {
                //当执行完毕后, 1,从runing队列移除, 2,并且满足条件,在从ready迭代,Remove放到runing中...
                client.dispatcher().finished(this);
            }
        }
    }

}

Dispatcher 分发器

分发器就是来调配请求任务,内部会包含一个线程池,当异步请求时候,会将任务讲给线程池来执行。

public synchronized ExecutorService executorService() {
    if (executorService == null) {
        executorService = new ThreadPoolExecutor(
            0,                                      //核心线程数
            Integer.MAX_VALUE,                      //最大线程
            60,                                     //空闲线程闲置时间
            TimeUnit.SECONDS,                       //闲置时间单位
            new SynchronousQueue(),       //线程等待队列 这是SynchronousQueue,没有容量的高并发,主要是外部有对任务请求的的runing和reday操作,这里就不需要线程池的操作
            Util.threadFactory("OkHttp Dispatcher", false)//线程创建工厂 Thread newThread(Runnable r);
        );
    }
    return executorService;
}

俩种队列

  1. running 执行队列 又分 存放同步 runningSyncCalls 和 异步 runningAsyncCalls
  2. ready 等待队列(异步)Deque readyAsyncCalls = new ArrayDeque<>()
  • **同步的分发器,直接add添加到 执行队列中 **

    Deque runningSyncCalls = new ArrayDeque<>(); 队列中...

  • 异步的分发器会进行判断进入哪个队列中,running执行 还是 ready等待 队列中
synchronized void enqueue(AsyncCall call) {
    //1、如果正在执行的请求小于64
    //2、相同host的请求不能超过5个
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
        runningAsyncCalls.add(call);  //正在执行的请求
        executorService().execute(call); //线程池跑任务
    } else {
        readyAsyncCalls.add(call);
    }
}

通过代码可以知晓,进入runningAsyncCalls异步执行队列必须满足2个条件:

    1. 如果正在执行的请求小于64      **考虑客户端请求压力**
    2. 相同host的请求不能超过5个    **考虑服务器Host压力**

否则就进入readyAsyncCalls等待队列

finished

移除当期执行完毕的队列,并且满足执行队列数目小于65,且同一Host中请求小于5才从ready队列取出放入runing队列。

    /**
     *
     * @param calls  当期所诉执行队列 同步/异步
     * @param call   泛型  同步RealCall 、 AsyncCall异步
     * @param promoteCalls  是否从等待队列中取(目前只有异步有ready队列)
     * @param 
     */
    private  void finished(Deque calls, T call, boolean promoteCalls) {
        int runningCallsCount;
        Runnable idleCallback;
        synchronized (this) {
            //在runing执行队列移除当期队列,因为执行完毕了。
            if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
            if (promoteCalls) promoteCalls();       //取等待队列
            runningCallsCount = runningCallsCount(); //同步+异步的正在执行任务数量
            idleCallback = this.idleCallback;
        }

        //如果没有正在执行的任务,且idleCallback不为null,则回调通知空闲了
        if (runningCallsCount == 0 && idleCallback != null) {
            idleCallback.run();
        }
    }

    /**
     * 从ready获取任务放入running执行
     */
    private void promoteCalls() {
        if (runningAsyncCalls.size() >= maxRequests) return; // 执行队列数目里大于64,不取
        if (readyAsyncCalls.isEmpty()) return; // 等待队列没有数据,不取

        //迭代Ready队列
        for (Iterator i = readyAsyncCalls.iterator(); i.hasNext(); ) {
            AsyncCall call = i.next();
            // 同一Host请求只能同时有5个
            if (runningCallsForHost(call) < maxRequestsPerHost) {
                i.remove();
                runningAsyncCalls.add(call);
                executorService().execute(call);
            }

            if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
        }
    }

Interceptor 拦截器

//拦截器集合  五大拦截器。有先后顺序(很重要)
Response getResponseWithInterceptorChain() throws IOException {
    // 有序队列
    List interceptors = new ArrayList<>();
    interceptors.addAll(client.interceptors()); //自定义拦截器加入到集合
    interceptors.add(RetryAndFollowUpInterceptor); //1、重定向拦截器
    interceptors.add(new BridgeInterceptor(client.cookieJar()));//2、Hander责任连拦截器
    interceptors.add(new CacheInterceptor(client.internalCache()));//3、缓存策略拦截器
    interceptors.add(new ConnectInterceptor(client));//4、连接拦截器,与服务器TCP完成连接
    if (!forWebSocket) {
        interceptors.addAll(client.networkInterceptors()); //自定义拦截器,只对非网页的请求生效
    }
    interceptors.add(new CallServerInterceptor(forWebSocket));//5、与服务器通讯,封装请求数据与解析响应拦截器

    Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
            originalRequest, this, eventListener, client.connectTimeoutMillis(),
            client.readTimeoutMillis(), client.writeTimeoutMillis());

    return chain.proceed(originalRequest);
}

五大拦截器:

  1. RetryAndFollowUpInterceptor:负责失败重试以及重定向
  2. BridgeInterceptor:负责把用户构造的请求转换为发送给服务器的请求,把服务器返回的响应转换为对用户友好的响应。
  3. CacheInterceptor:负责读取缓存以及更新缓存
  4. ConnectInterceptor:连接拦截器,与服务器TCP完成连接
  5. CallServerInterceptor:与服务器通讯,封装请求数据与解析响应拦截器

你可能感兴趣的:(OkHttp源码流程分析)