`
daojin
  • 浏览: 690220 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

OKHttp3.14.5源代码解析

 
阅读更多
Rxjava:
https://www.jianshu.com/p/7474950af2df

基本使用方式
创建Request

Request request = new Request.Builder().url().get().build(); 


创建OkHttpClient
OkHttpClient client = new OkHttpClient(); 
 
public final OkHttpClient client = new OkHttpClient.Builder() 
        .addInterceptor(new HttpLoggingInterceptor()) 
        .cache(new Cache(cacheDir, cacheSize)) 
        .build(); 
 
 
   OkHttpClient client = client.newBuilder() 
        .readTimeout(500, TimeUnit.MILLISECONDS) 
       .build(); 


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

client.newCall(request).enqueue(callback);


清理

client.dispatcher().executorService().shutdown();
client.connectionPool().evictAll();
 client.cache().close();


代码流程分析
创建RealCall
  private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    this.client = client;
    this.originalRequest = originalRequest;
    this.forWebSocket = forWebSocket;
  }

  static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    // Safely publish the Call instance to the EventListener.

如果是同步的call
直接调用RealCall.execute

 private int maxRequests = 64;			
		  private int maxRequestsPerHost = 5;			
					
  @Override public Response execute() throws IOException {					
    synchronized (this) {					
      if (executed) throw new IllegalStateException("Already Executed");					
      executed = true;					
    }					
    transmitter.timeoutEnter();					
    transmitter.callStart();					
    try {					
      client.dispatcher().executed(this);					
      return getResponseWithInterceptorChain();					
    } finally {					
      client.dispatcher().finished(this);					
    }					
  }

如若调用enqueue方法,就会走到AsyncCall
  @Override public void enqueue(Callback responseCallback) {					
    synchronized (this) {					
      if (executed) throw new IllegalStateException("Already Executed");					
      executed = true;					
    }					
    transmitter.callStart();					
    client.dispatcher().enqueue(new AsyncCall(responseCallback));					
  }					
	

AsyncCall是Runnalbe 包装了callback

client.dispatcher().enqueue调用了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.					
        if (asyncCall.callsPerHost().get() >= maxRequestsPerHost) continue; // Host max capacity.					
					
        i.remove();					
        asyncCall.callsPerHost().incrementAndGet();					
        executableCalls.add(asyncCall);					
        runningAsyncCalls.add(asyncCall);					
      }					
      isRunning = runningCallsCount() > 0;					
    }					
					
    for (int i = 0, size = executableCalls.size(); i < size; i++) {					
      AsyncCall asyncCall = executableCalls.get(i);					
      asyncCall.executeOn(executorService());					
    }					
					
    return isRunning;					
  }					
					
					
 asyncCall.executeOn(executorService());					
					

					
    /**					
     * Attempt to enqueue this async call on {@code executorService}. This will attempt to clean up					
     * if the executor has been shut down by reporting the call as failed.					
     */					
    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);					
        transmitter.noMoreExchanges(ioException);					
        responseCallback.onFailure(RealCall.this, ioException);					
      } finally {					
        if (!success) {					
          client.dispatcher().finished(this); // This call is no longer running!					
        }					
      }					
    }	

下面执行到了execute,调用 Response response = getResponseWithInterceptorChain();

 
   @Override protected void execute() {					
      boolean signalledCallback = false;					
      transmitter.timeoutEnter();					
      try {					
        Response response = getResponseWithInterceptorChain();					
        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 {					
          responseCallback.onFailure(RealCall.this, e);					
        }					
      } catch (Throwable t) {					
        cancel();					
        if (!signalledCallback) {					
          IOException canceledException = new IOException("canceled due to " + t);					
          canceledException.addSuppressed(t);					
          responseCallback.onFailure(RealCall.this, canceledException);					
        }					
        throw t;					
      } finally {					
        client.dispatcher().finished(this);					
      }					
    }					
					
getResponseWithInterceptorChain() 					
  Response getResponseWithInterceptorChain() throws IOException {					
    // Build a full stack of interceptors.					
    List<Interceptor> interceptors = new ArrayList<>();					
    interceptors.addAll(client.interceptors());					
    interceptors.add(new RetryAndFollowUpInterceptor(client));					
    interceptors.add(new BridgeInterceptor(client.cookieJar()));					
    interceptors.add(new CacheInterceptor(client.internalCache()));					
    interceptors.add(new ConnectInterceptor(client));					
    if (!forWebSocket) {					
      interceptors.addAll(client.networkInterceptors());					
    }					
    interceptors.add(new CallServerInterceptor(forWebSocket));					
					
    Interceptor.Chain chain = new RealInterceptorChain(interceptors, transmitter, null, 0,					
        originalRequest, this, client.connectTimeoutMillis(),					
        client.readTimeoutMillis(), client.writeTimeoutMillis());					
					
    boolean calledNoMoreExchanges = false;					
    try {					
      Response response = chain.proceed(originalRequest);					
      if (transmitter.isCanceled()) {					
        closeQuietly(response);					
        throw new IOException("Canceled");					
      }					
      return response;					
    } catch (IOException e) {					
      calledNoMoreExchanges = true;					
      throw transmitter.noMoreExchanges(e);					
    } finally {					
      if (!calledNoMoreExchanges) {					
        transmitter.noMoreExchanges(null);					
      }					
    }					
  }					
RealInterceptorChain.proceed					
					
					
  public Response proceed(Request request, Transmitter transmitter, @Nullable Exchange exchange)					
      throws IOException {					
					
					
 Response response = interceptor.intercept(next);					
					
}	


接下来走到Interceptor.intercept
RealCall.getResponseWithInterceptorChain 可以看到有四个					
    interceptors.add(new RetryAndFollowUpInterceptor(client));					
    interceptors.add(new BridgeInterceptor(client.cookieJar()));					
    interceptors.add(new CacheInterceptor(client.internalCache()));					
    interceptors.add(new ConnectInterceptor(client));					
CallServerInterceptor	



RetryAndFollowUpInterceptor 处理3XX重定向的,4XX授权,5xx服务器错误retry等

Location
  @Override public Response intercept(Chain chain)
Request followUp = followUpRequest(response, route);
 case HTTP_MULT_CHOICE:
      case HTTP_MOVED_PERM:
      case HTTP_MOVED_TEMP:
      case HTTP_SEE_OTHER:
        // Does the client allow redirects?
        if (!client.followRedirects()) return null;

        String location = userResponse.header("Location");


BridgeInterceptor
添加了很多header,并且加入了gzip

CacheInterceptor 处理cache
ConnectInterceptor 创建Exechange,建立连接
CallServerInterceptor 调用

exchange.writeRequestHeaders(request);					
					
  if (responseBuilder == null) {					
      responseBuilder = exchange.readResponseHeaders(false);					
    }					
					
    Response response = responseBuilder					
        .request(request)					
        .handshake(exchange.connection().handshake())					
        .sentRequestAtMillis(sentRequestMillis)					
        .receivedResponseAtMillis(System.currentTimeMillis())					
        .build();					
			



题外话:
ConnectionPool
最大5个链接,最长 5分钟
实现是RealConnectionPool

Http1.0 很明显无法复用socket链接。

Http2.0 可以复用socket链接







分享到:
评论

相关推荐

    okHttp访问返回JSON,XML解析实例

    本篇将详细讲解如何使用OkHttp进行网络访问,并解析返回的JSON与XML数据。 首先,我们需要了解OkHttp的基本用法。OkHttp是一个异步的HTTP客户端,它通过减少网络延迟和内存使用来提高性能。创建一个OkHttpClient...

    okhttp请求+FastJson解析数据

    "okhttp请求+FastJson解析数据"这个主题聚焦于两个关键库的使用:OkHttp用于发起网络请求,FastJson则用于处理返回的数据,进行JSON解析。下面我们将深入探讨这两个库及其在实际开发中的应用。 首先,OkHttp是...

    java 调用okHttp3进行代码测试(SpringBoot项目))

    在Java代码中,创建一个OkHttpClient实例,并使用build()方法配置客户端参数。然后,通过new Request.Builder()构建请求对象,设置URL,最后使用OkHttpClient的newCall(request).execute()执行请求并获取响应。 ```...

    Android-简单封装OKhttpRetrofitRxjava代码支持参数加密解密按需选择库

    简单封装OKhttp Retrofit Rxjava代码,支持参数加密解密,按需选择库,支持日志库按需选择,支持主动取消请求,支持json,表单请求,暂只支持get,post请求方式两种,支持单点登录,一行代码发起请求

    安卓即时通讯工具源代码

    1. **用户身份验证**:用户注册和登录通常涉及到服务器端的数据存储和验证,源代码中可能会包含网络请求库(如OkHttp或Volley)的使用,以及JSON解析(如Gson或Jackson)来处理服务器返回的数据。 2. **消息传输**...

    okhttp3.12.1+okio1.14.1

    2. **源(Source)和Sink**:Okio 将输入和输出抽象为 Source 和 Sink 接口,使得数据操作更加灵活。 3. **快速的文件操作**:Okio 提供了快速的文件读写方法,支持分块读写和随机访问。 4. **流转换**:Okio 可以...

    随手记 Android 源代码

    《随手记 Android 源代码解析与学习指南》 随手记是一款广受欢迎的个人财务管理应用,其Android版本的源代码提供了深入理解移动应用开发的宝贵资料。这份源代码的公开,为开发者提供了一个实践和研究Android应用...

    Okhttp示例代码

    本示例代码将帮助你理解如何在实际项目中使用 OkHttp 进行网络请求。 首先,让我们了解 OkHttp 的基本使用: 1. **创建 OkHttpClient 实例**: 在 OkHttp 中,`OkHttpClient` 是主要的配置对象,它包含了网络请求...

    Android经典项目开发实战_源代码

    源代码会展示如何使用Gson、Jackson或org.json库解析JSON数据。 8. **异步处理**:为了保持UI的响应性,非阻塞的异步操作是必不可少的。源码可能包含了使用AsyncTask、Handler、IntentService或现代的LiveData和...

    okhttp-2.7.1-API文档-中英对照版.zip

    赠送源代码:okhttp-2.7.1-sources.jar; 赠送Maven依赖信息文件:okhttp-2.7.1.pom; 包含翻译后的API文档:okhttp-2.7.1-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:...

    wordpress Android客户端源代码

    【WordPress Android客户端源代码解析】 WordPress作为全球最受欢迎的开源博客平台,其Android客户端的源代码对于开发者来说具有极高的学习价值。这份源代码不仅能够帮助我们深入理解Android应用的开发流程,还能让...

    OkHttp3源码解析(添加了详细注释)

    **OkHttp3源码解析** OkHttp3是Android平台上的一个高效、易用的网络通信库,由Square公司开发。它的出现解决了Android原生HttpURLConnection的性能问题,提供了更强大的功能和更好的网络请求管理。本解析主要围绕...

    新浪微博android源代码

    源代码可能包含了对Apache HttpClient或OkHttp等网络库的使用,以及对JSON数据格式的解析。理解这些网络通信机制,有助于我们优化请求性能,处理网络异常,实现离线模式等功能。 2. **数据缓存**:为了提高用户体验...

    json 源代码

    在你提供的信息中,“json 源代码”可能是指用于处理JSON数据的源代码库,例如解析、生成和操作JSON对象的函数或类。Android框架也包含对JSON的支持,这部分源代码可能是从Android框架中提取出来的一个部分,供...

    7个Android应用程序源代码-巅峰版

    源代码中可能会展示如何处理API调用、JSON解析和异步任务。 5. **多媒体处理**:Android支持音频、视频和图像的处理。源代码可能包含如何使用MediaPlayer、ExoPlayer、Camera API以及Bitmap和 Glide 图像加载库的...

    7个Android应用程序源代码

    源代码可能包含了使用HttpURLConnection、OkHttp或Retrofit等库进行网络请求的示例。 6. **异步处理**:Android应用的主线程负责UI更新,因此需要避免在主线程执行耗时操作。源代码可能使用了AsyncTask、...

    一个android 新闻客户端的参考源代码.rar

    源代码的解析是基于HTML的,这意味着它可能利用了网络上的HTML内容来展示新闻,这在许多新闻应用中很常见,因为网页内容可以通过网络接口获取并本地化显示。 首先,我们要理解Android开发的基本概念。Android是一个...

    okhttp封装json解析

    通过OkHttp的高效网络通信和Gson的便捷数据转换,可以大大提高开发效率,并且使代码更加模块化和易于维护。对于初学者来说,这是一个很好的起点,而对于经验丰富的开发者来说,这提供了一个可扩展的基础,可以根据...

    传智播客Android视频教程_源代码zip

    源代码会展示如何使用HttpURLConnection、OkHttp或者Retrofit等库进行网络通信。 6. **多线程**:Android应用的主线程(UI线程)不能执行耗时操作,否则会导致应用无响应。源代码会演示如何使用AsyncTask、Handler...

Global site tag (gtag.js) - Google Analytics