okhttp大概流程

OkHttp网络请求流程浅析,纯个人学习记录。如有错误,希望大家指正。

  1. 实例化OkHttpClient
    使用okhttp请求网络,首先得实例化一个OkHtppClient对象。
    OkHttpClient对象是通过OkHttpClient中的构造器对象Builder创建。所以先实例化OkHttpClient中的Builder类。
OkHttpClient client;
OkHttpClient.Builder builder = new OkHttpClient.Builder();

初始化Builder源码 源码中初始化了一些默认参数

 public Builder() {
      dispatcher = new Dispatcher();//分发
      protocols = DEFAULT_PROTOCOLS; //协议
      connectionSpecs = DEFAULT_CONNECTION_SPECS;
      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;//默认写入时间
    }

初始化之后可以通过builder对上述默认参数进行修改,然后返回OkhttpClient对象,代码如下:

 OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request().newBuilder().build();
                return chain.proceed(request);
            }
        });//设置拦截器
        builder.connectTimeout(120L, TimeUnit.SECONDS);//设置链接超时
        client = builder.build();//返回OkHttpClient对象
  1. Get请求方式请求网络
    初始化request 请求体 ,通过request builder 构造器实例化一个默认GET请求的请求体 可修改head url methed。
Request request = new Request.Builder()
                .url(url).build();

RequestBuilder构造方法中默认就是一个Get方式的网络请求体所以我们不需要设置请求方式。

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

然后通过client的newCall方法获取一个Call类型的实例

Call call = client.newCall(request);

通过源码可以看到返回的是一个实现了Call接口的RealCall类

@Override public Call newCall(Request request) {
    return new RealCall(this, request);
  }

最后通过Call.execute()方法执行请求并返回信息。execute()是一个同步请求执行方式。异步执行调用Call.enqueue()
同步请求

 try {
           Response response =  call.execute();
        } catch (IOException e) {
            e.printStackTrace();
        }

异步请求

call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

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

            }
        });

同步请求源码

@Override public Response execute() throws IOException {
    synchronized (this) { 
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    try {
      client.dispatcher().executed(this);//添加到拦截器的deque集合中
      Response result = getResponseWithInterceptorChain(false);
      if (result == null) throw new IOException("Canceled");
      return result;
    } finally {
      client.dispatcher().finished(this);
    }
  }

最后执行返回结果体

@Override public Response proceed(Request request) throws IOException {
      // If there's another interceptor in the chain, call that.
      if (index < client.interceptors().size()) {
        Interceptor.Chain chain = new ApplicationInterceptorChain(index + 1, request, forWebSocket);
        Interceptor interceptor = client.interceptors().get(index);
        Response interceptedResponse = interceptor.intercept(chain);

        if (interceptedResponse == null) {
          throw new NullPointerException("application interceptor " + interceptor
              + " returned null");
        }

        return interceptedResponse;
      }

      // No more interceptors. Do HTTP.
      return getResponse(request, forWebSocket);

异步执行源码流程

void enqueue(Callback responseCallback, boolean forWebSocket) {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    client.dispatcher().enqueue(new AsyncCall(responseCallback, forWebSocket));//初始化一个AcyncCall线程添加到dispathcer中的集合然后执行
  }

dispatcher中enqueue方法

synchronized void enqueue(AsyncCall call) {
如果线程池中执行数已满先放到集合中等待
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
      runningAsyncCalls.add(call);//添加到集合中
      executorService().execute(call);放到线程池中执行
    } else {
      readyAsyncCalls.add(call);
    }
  }
  1. POST请求
    POST请求流程跟GET请求流程一样,只是多了一个请求体
    RequestBody;
RequestBody body = new FormBody.Builder().build();
        Request request = new Request.Builder().url(url).post(body).build();
        Call call = client.newCall(request);
        try {
            call.execute();
        } catch (IOException e) {
            e.printStackTrace();
        }

猜你喜欢

转载自blog.csdn.net/zouwei_199388/article/details/80640320