OkHttp3源码详解(二整体流程)

     上一篇文章已经对Request相关的类进行了详细的学习,后面我发现Okhttp这种底层框架一个类一个类看没什么用,所以这篇文章开始就只对Okhttp的整体流程作一个学习

   1.简单的get请求

  

   Request request = new Request.Builder()
                .url("https://www.baidu.com/")
                .build();

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

            }

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

            }
        });

  我们来看一下RealCall中的enqueue的逻辑看一下,
  @Override public void enqueue(Callback responseCallback) {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }

这个方法调用Dispatcher的enqueue方法

 synchronized void enqueue(AsyncCall call) {
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
      //正在运行的异步任务队列数量小于最大请求数,线程池执行该任务
      runningAsyncCalls.add(call);
      executorService().execute(call);
    } else {
      //把该方法放到异步任务准备队列中
      readyAsyncCalls.add(call);
    }
  }

线程池执行该异步任务,会执行异步任务的run方法,run方法中调用了execute抽象方法,我们来看一下这个方法的实现

@Override protected void execute() {
      boolean signalledCallback = false;
      try {
        //由getResponseWithInterceptorChain()来执行网络请求,得到response
        Response response = getResponseWithInterceptorChain();
        if (retryAndFollowUpInterceptor.isCanceled()) {
          signalledCallback = true;
          //失败后回调Callback的onFailure方法
          responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
        } else {
          signalledCallback = true;
          //成功后回调CallBack的onResponse方法
          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 {
          responseCallback.onFailure(RealCall.this, e);
        }
      } finally {
        //最后调用Dispatcher的finish方法
        client.dispatcher().finished(this);
      }
    }
  

我们先来看finish方法,后面再去看getResponseWithInterceptorChain(),来解决简单的再去看复杂的

  void finished(AsyncCall call) {
    finished(runningAsyncCalls, call, true);
  }

  private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
    int runningCallsCount;
    Runnable idleCallback;
    synchronized (this) {
      if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
      //promoteCalls()该方法会去从异步准备运行的队列中去取任务去执行
      if (promoteCalls) promoteCalls();
      //得到异步和同步任务正在执行数
      runningCallsCount = runningCallsCount();
      idleCallback = this.idleCallback;
    }
    //如果设置了该线程,执行回调线程
    if (runningCallsCount == 0 && idleCallback != null) {
      idleCallback.run();
    }
  }

走完一个流程后我们来看一下getResponseWithInterceptorChain()方法的实现细节,这个方法在call.execute()也调用到了,OkHttp中真正发出网络请求,解析返回结果的,就是这个方法

private Response getResponseWithInterceptorChain() throws IOException {

    //构建全栈拦截器
    List interceptors = new ArrayList<>();
    interceptors.addAll(client.interceptors());//自定义拦截器
    interceptors.add(retryAndFollowUpInterceptor);//重试拦截器
    interceptors.add(new BridgeInterceptor(client.cookieJar()));//桥接拦截器
    interceptors.add(new CacheInterceptor(client.internalCache()));//缓存拦截器
    interceptors.add(new ConnectInterceptor(client));//连接拦截器
    if (!retryAndFollowUpInterceptor.isForWebSocket()) {
      interceptors.addAll(client.networkInterceptors());//用户预定义的网络拦截器
    }
    interceptors.add(new CallServerInterceptor(
        retryAndFollowUpInterceptor.isForWebSocket()));//调用服务拦截器

    //内部通过责任链模式来使用拦截器
    Interceptor.Chain chain = new RealInterceptorChain(
        interceptors, null, null, null, 0, originalRequest);

    return chain.proceed(originalRequest);//获取Response
  }

这么多的拦截器,看着肯定很懵逼吧,是的我就是这样。我们就一个一个的来看吧


RetryAndFollowUpInterceptor

     重试与重定向拦截器,用来实现重试和重定向功能,内部通过while(true)死循环来进行重试获取Response(有重试上限,超过会抛出异常)。followUpRequest主要用来根据响应码来判断属于哪种行为触发的重试和重定向(比如未授权,超时,重定向等),然后构建响应的Request进行下一次请求。当然,如果没有触发重新请求就会直接返回Response。

 

BridgeInterceptor

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OkHttp是一个开源的HTTP客户端库,用于在Android和Java应用程序中进行网络请求。它提供了简单且强大的API,使得发送和接收HTTP请求变得更加容易。在使用OkHttp时,首先需要创建一个OkHttpClient实例,该实例用于配置和执行HTTP请求。然后,可以使用OkHttpClient创建一个Request对象,该对象包含了请求的URL、请求头和请求体等信息。接下来,可以使用OkHttpClient的newCall方法创建一个Call对象,该对象表示一个异步的HTTP请求任务。可以通过调用Call对象的enqueue方法来执行异步请求,并传入一个Callback对象来处理请求的响应结果。在Callback对象的onResponse方法中,可以获取到请求的响应数据,而在onFailure方法中,可以处理请求失败的情况。[1] OkHttp和Retrofit是相辅相成的,Retrofit是对OkHttp的上层封装,它提供了更加简洁和高级的API来进行网络请求。在使用OkHttp时,可以通过创建一个OkHttpClient实例来配置网络请求的一些参数,例如连接超时时间、读取超时时间等。然后,可以使用OkHttpClient创建一个Request对象,该对象包含了请求的URL、请求头和请求体等信息。接下来,可以使用OkHttpClient的newCall方法创建一个Call对象,该对象表示一个异步的HTTP请求任务。可以通过调用Call对象的enqueue方法来执行异步请求,并传入一个Callback对象来处理请求的响应结果。[2] 在OkHttp中,execute方法表示同步请求,即在当前线程中执行网络请求,而enqueue方法表示异步请求,即使用OkHttp内置的线程池来执行网络请求。这涉及到OkHttp的任务分发器,它负责将请求任务分发给线程池中的线程来执行。通过使用异步请求,可以避免在主线程中进行网络请求,从而提高应用的响应速度和用户体验。[3]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值