关闭

Android网络框架:OKHttp源码简单解析(一)

标签: android源码okhttp框架
1964人阅读 评论(0) 收藏 举报
分类:

这是第一次解析源码并把它写出来,在之前,我一直以为只要会用别人的轮子就好,做出实际的效果就行,对看源码对自己的能力提升不以为然。后来偶然听到一句话:看别人的DEMO,你就可以会用轮子,但是要想用好轮子,还是得看源码。我觉得看源码有两个方面的好处:

 1. 从本质上去理解所学框架的原理和流程;
 2. 可以看到软件开发里常见的思维方法和设计模式;这些在编程里都是相通的。

下面这篇文章,我们队OkHttp框架做一个简单的分析。
使用OkHttp访问网络,通用的做法就是下面四步:

 步骤: 
 //1 创建okHttpClient对象
 //2 创建网络Request对象
 //3 创建与Request对应的返回Call对象
 //4 请求加入调度(直接执行)

在第四步中,访问网络有两种方式,一种是同步请求访问网络。一种是异步请求访问网络,我们先看看同步访问网络是怎么实现的。

同步访问网络实现源码解析:它是通过okHttpClient.newCall(re)创建一个Call对象。如下:

 OkHttpClient okHttpClient =new OkHttpClient();
 Response response = okHttpClient.newCall(request).execute();
 Request request = new Request.Builder()
                .url("http://publicobject.com/helloworld.txt")
                .build();
 Call call=okHttpClient.newCall(request);
 Response response = call.execute();
 if(response.isSuccessful()){             Log.i("TAG","response.code()="+response.code());//200           Log.i("TAG","response.body().string()="+response.body().string());
        }

这里我们先看看Call对象到底是什么鬼?跟踪源码我们可以看到:

/**
   * Prepares the {@code request} to be executed at some point in the future.//准备一个在未来某个点会被执行的网络请求
   */
  @Override public Call newCall(Request request) {
    return new RealCall(this, request);
  }

可以看到真正起作用的是RealCall,并非我们看到的Call;我们再看看RealCall是什么?

final class RealCall implements Call {//RealCall是一个继承了Call接口的网络真正请求类,
  private final OkHttpClient client;
 ....
  protected RealCall(OkHttpClient client, Request originalRequest) {
    this.client = client;
    this.originalRequest = originalRequest;
  }
//真正执行execute的地方;
  @Override public Response execute() throws IOException {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    try {
      client.dispatcher().executed(this);
      Response result = getResponseWithInterceptorChain(false);
      if (result == null) throw new IOException("Canceled");
      return result;
    } finally {
      client.dispatcher().finished(this);
    }
  }

上面代码中,client.dispatcher().executed(this);是将当前网络请求,从OkHttpClient获得的Dispatcher然后把它加入到分发器里面的队列 executedCalls中,在完成的时候会remove掉,源码如下:

  synchronized void executed(RealCall call) {
    runningSyncCalls.add(call);
  }

  synchronized void finished(Call call) {
    if (!runningSyncCalls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
  }

上面中的runningSyncCalls是指正在执行的同步任务队列,在OkHttp框架中对网络请求进行分发任务的是Dispatcher类,Dispatcher维护了如下变量,用于控制并发的请求

  private int maxRequests = 64;//最大并发请求数为64
  private int maxRequestsPerHost = 5;//每个主机最大请求数为5
  private ExecutorService executorService;//线程池
  private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();//维护准备执行的异步请求队列,双端队列缓存(用数组实现,可自动扩容,无大小限制);
  private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();//正在执行的异步任务队列,包括已经取消但是并未finish的请求
  private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();//正在执行的同步任务队列,包括已经取消但是并未finish的请求

Dispatcher: 分发者,也就是生产者(默认在主线程)
AsyncCall: 队列中需要处理的Runnable(包装了异步回调接口)
ExecutorService:消费者池(也就是线程池)
根据生产者消费者模型的模型理论,当入队(enqueue)请求时,如果满足(runningRequests<64 && runningRequestsPerHost<5),那么就直接把AsyncCall直接加到runningCalls的队列中,并在线程池中执行。如果消费者缓存满了,就放入readyAsyncCalls进行缓存等待。

0
0
查看评论

Android 网络框架之Retrofit2使用详解及从源码中解析原理

就目前来说Retrofit2使用的已相当的广泛,那么我们先来了解下两个问题:1 . 什么是Retrofit?Retrofit是针对于Android/Java的、基于okHttp的、一种轻量级且安全的、并使用注解方式的网络请求框架。2 . 我们为什么要使用Retrofit,它有哪些优势?首先,Retr...
  • guiman
  • guiman
  • 2016-05-26 16:32
  • 22820

Android通用网络请求解析框架.3(代码实现,公共部分)

笔者将通过10篇博客对个人开源框架进行讲解,本篇为第3篇,讲解代码实现,公共部分。 开源库github地址 https://github.com/qq296216078/Android-Universial-NetFrame 如果有兴趣一起讨论本框架的内容,请加QQ群:27133...
  • qq_296216078
  • qq_296216078
  • 2017-01-05 20:52
  • 394

okHttp框架原理

Android中网络请求框架比较多,常用的有HttpURLConnection,Volley,okHttp,Retrofit,RxJava等 从Android4.4开始HttpURLConnection底层实现采用的是okHttp 进行通信的原理是: 主要是通过dispatcher不断从r...
  • ami_daqi
  • ami_daqi
  • 2016-12-19 17:31
  • 1770

okhttp框架实现注册登录

OkHttp 相较于其它的实现有以下的优点: 1. 支持SPDY,允许连接同一主机的所有请求分享一个socket。 如果SPDY不可用,会使用连接池减少请求延迟。 使用GZIP压缩下载内容,且压缩操作对用户是透明的。 利用响应缓存来避免重复的网络请求。 当网络出现问题的时候,OKHttp会依然有...
  • Banboofly
  • Banboofly
  • 2016-10-26 09:38
  • 3392

Android OkHttp框架解析

Okhttp是由Sqare公司开发的开源网络访问库,是目前比较火的网络框架, 它处理了很多网络疑难杂症:会从很多常用的连接问题中自动恢复。如果你的服务器配置了多个IP地址,当第一个IP连接失败的时候,OkHttp会自动尝试下一个IP,此外OkHttp还处理了代理服务器问题和SSL握手失败问题。 首...
  • huaxun66
  • huaxun66
  • 2016-09-21 21:14
  • 4412

优雅设计封装基于Okhttp3的网络框架(一):Http网络协议与Okhttp3解析

如今Android开发中Okhttp已成为主流网络框架,内置丰富、全面、强大的网络请求功能,也为开发者提供了api,但是在项目开发中的大量使用,会出现api的重复调用、代码冗杂等现象。应当封装一个适用于项目的网络框架,便于使用。此系列文章旨于:基于okhttp3原始框架来设计封装一个满足业务需求、扩...
  • ITermeng
  • ITermeng
  • 2017-07-04 16:36
  • 1702

okhttp简单介绍

Android网络请求库比较多,常用的HttpURLConnection、volley、okhttp、retrofit等。 Android开发常见的第三方框架:http://blog.csdn.net/liuhaomatou/article/details/44857005  从And...
  • Jack_Chen3
  • Jack_Chen3
  • 2016-04-18 21:44
  • 2464

老罗视频第二季重磅来袭:Android Studio工具讲解

老罗Android视频讲解 支持老罗Android视频,学习Android技术!学习是一种信仰! Android Studio工具讲解: 关于Android Studio工具点击即可下载! 视频下载!
  • qq_21811237
  • qq_21811237
  • 2016-04-25 16:54
  • 1064

okhttp,Android网络框架学习之OKHttp

http://blog.csdn.net/lmj623565791/article/details/49734867一、概述之前写了篇Android OkHttp完全解析 是时候来了解OkHttp了,其实主要是作为okhttp的普及文章,当然里面也简单封装了工具类,没想到关注和使用的人还挺多的,由于...
  • Xs15073722800
  • Xs15073722800
  • 2016-04-21 15:22
  • 882

Android网络框架学习之OkHttp

OkHttp官网地址 OkHttp GitHub地址 官网中有很详细的Java doc文档,我们可以很方便的查到OkHttp里面各个API的功能和使用方法。get方式获取数据private String doGet(String areaId) { //1.创建一个okClie...
  • zoky_ze
  • zoky_ze
  • 2017-03-01 09:45
  • 388
    个人资料
    • 访问:183299次
    • 积分:2769
    • 等级:
    • 排名:第15275名
    • 原创:102篇
    • 转载:9篇
    • 译文:1篇
    • 评论:24条
    博客专栏
    最新评论