对于okhttp在如今项目中的普及程度已经不言而喻啦,基本上如今网络请求都会基于它去进行封装,而非前几年用Android的网络框架HttpURLConnection和Apache HttpClient去进行底层网络访问的封装了,就目前而言它应该是最火热的网络请求开源项目了,既然这么多公司的项目都采用它肯定是有原因的,所以百度百科上对它的优劣列举了下:

另外再闲扯一下,它是由移动支付Square公司贡献的,说到Square,我想有一位Android大神不得不提,看图说话:

其中它对okhttp的贡献相当之大:

好了,回到正题,对于这么优秀的一个开源框架,如果只是停留在如何使用它貌似确实有点浪费了,另外还有一个原因就是如今android面试并非前几年了,对于技术的要求也越来越高了,而面试中只问你如何在项目中使用主流的三方开源框架我想是越来越少了,所以,接下来准备一点点去从源码的角度去分析它的机制,当然由于它的代码量巨大,要想全部搞明白那也挺费尽的,重点是从其流程原理上进行有针对性的分析。

在正式进行源码分析之前先来看一下使用okhttp如何网络请求,而它提供了两种请求方式:同步和异步,下面开始。

同步请求:

首先加入okhttp的官方依赖,这里采用okhttp3.9.0这个版本进行学习,首先在gradle中加入依赖:

接着在界面中增加一个按钮,点击它则进行同步请求:

而具体代码的实现过程如下:

1、创建OkHttpClient对象:

对于HttpClient我们都很熟悉,这是之前Android库中的网络使用对象,回忆一下:

而在使用okhttp时,第一步其实也是类似,需要创建OkHttpClient,如下:

上面这句代码就已经将OkHttpClient创建完了么?试想一下对于网络请求是不是得配置很多的一些参数,如网络超时等,而对于参数的配置最适合最优雅的方式则是采用Builder模式,而OkHttpClient对于参数的构建就是这么搞的,所以将其改为用Builder模式去构建如下:

其中设置了5秒的读取超时时间,当然还可以设置非常多的参数,点一下就可以看到:

其怎么使用Builder模式,这个之后在源码分析中会详细去阅读的,不过这里可以简单的瞅一眼大致构建过程,那就打开OkHttpClient的源代码:

而针对每个参数定义了一个对外调用的方法,方法的重点是返回Builder这个内部类对象自身,这样就可以不断的以点的方式链式的进行参数的配置,以咱们已经使用到的readTimeout()为例:

当所有参数都设置完毕之后,最后调用它的build()方法进行OkHttpClient对象的构建,如下:

基于上已经分析清楚了使用Builder模式的步骤,在实际开发中如果遇到有很多参数要进行配置利用这个模式体验上会比较好,可以校仿一下。

2、创建Request对象:

对于这个对象的创建也是采用Builder方式进行构建,可见Builder模式还是相当好用的,因为在这个对象中也是有一些参数需要进行配置,如URL、请求方式等,所以下面就不过多的解释了,直接上代码:

上面是采用get方式,对比一下咱们传统的代码,其实也差不多,传统代码中用HttpGet来直观的表达请求:

3、将Request封装成Call对象:

对于Request和OkHttpClient如何关连起来呢?这里就它这种关联封装成了Call对象了,如下:

4、调用Call的execute()发送同步请求:

最后咱们运行看一下效果,当然在运行之前需要给app加入访问网络的权限,这里就不多说了:

足以证明它确实是以同步的方式去请求网络的,要想不报错那当然得将这个请求放到子线程喽,于是乎:

再次编译运行:

异步请求:

先增加一个异步请求的button:

相比上面的同步请求,异步请求的实现步骤基本上差不多,如下:

1、创建OkHttpClient对象:

2、创建Request对象:

3、将Request封装成Call对象:

4、调用Call的enqueue方法进行异步请求:

但是,其实OkhttpClient对于APP而言只要创建一次既可,并不用每次请求就得创建一下它,所以可以将它提取出来,由每个不同的请求共享它:

public class MainActivity extends AppCompatActivity {

    private static final OkHttpClient OK_HTTP_CLIENT = new OkHttpClient.Builder()
.readTimeout(5, TimeUnit.SECONDS)
.build(); @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
} /**
* 同步请求
*/
public void synRequest(View view) {
new Thread(new Runnable() {
@Override
public void run() {
//2、创建Request对象
final Request request = new Request.Builder().url("http://www.baidu.com")
.get().build();
//3、将Request封装成Call对象
Call call = OK_HTTP_CLIENT.newCall(request);
//4、调用Call的execute()发送同步请求
try {
Response response = call.execute();
Log.e("cexo", response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
} /**
* 异步请求
*/
public void asycRequest(View view) {
//2、创建Request对象
final Request request = new Request.Builder().url("http://www.baidu.com")
.get().build();
//3、将Request封装成Call对象
Call call = OK_HTTP_CLIENT.newCall(request);
//4、调用Call的enqueue方法进行异步请求
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e("cexo", "request failed:" + e.getMessage());
} @Override
public void onResponse(Call call, Response response) throws IOException {
Log.e("cexo", "request successed:" + response.body().string());
}
});
}
}

编译运行:

可见确实是在子线程执行的,也说明是异步请求。

【注意】:异步请求回调onResponse()和onFailure()方法都是在子线程执行的,这个是比较容易忽视的,下面来实验下:

编译运行:

总结:

对于OkHttp的同步和异步请求需要记住的是:

1、发起请求的方法调用:同步请求是调用Call.execute();异步请求是调用Call.enqueue()。

2、阻塞线程与否:同步阻塞、异步不阻塞。

okhttp框架源码分析从同步&异步请求使用开始的更多相关文章

  1. Spark RPC框架源码分析(一)简述

    Spark RPC系列: Spark RPC框架源码分析(一)运行时序 Spark RPC框架源码分析(二)运行时序 Spark RPC框架源码分析(三)运行时序 一. Spark rpc框架概述 S ...

  2. Spark RPC框架源码分析(二)RPC运行时序

    前情提要: Spark RPC框架源码分析(一)简述 一. Spark RPC概述 上一篇我们已经说明了Spark RPC框架的一个简单例子,Spark RPC相关的两个编程模型,Actor模型和Re ...

  3. Android Small插件化框架源码分析

    Android Small插件化框架源码分析 目录 概述 Small如何使用 插件加载流程 待改进的地方 一.概述 Small是一个写得非常简洁的插件化框架,工程源码位置:https://github ...

  4. YII框架源码分析(百度PHP大牛创作-原版-无广告无水印)

           YII 框架源码分析    百度联盟事业部——黄银锋 目 录 1. 引言 3 1.1.Yii 简介 3 1.2.本文内容与结构 3 2.组件化与模块化 4 2.1.框架加载和运行流程 4 ...

  5. Spark RPC框架源码分析(三)Spark心跳机制分析

    一.Spark心跳概述 前面两节中介绍了Spark RPC的基本知识,以及深入剖析了Spark RPC中一些源码的实现流程. 具体可以看这里: Spark RPC框架源码分析(二)运行时序 Spark ...

  6. iOS常用框架源码分析

    SDWebImage NSCache 类似可变字典,线程安全,使用可变字典自定义实现缓存时需要考虑加锁和释放锁 在内存不足时NSCache会自动释放存储的对象,不需要手动干预 NSCache的key不 ...

  7. 介绍开源的.net通信框架NetworkComms框架 源码分析

    原文网址: http://www.cnblogs.com/csdev Networkcomms 是一款C# 语言编写的TCP/UDP通信框架  作者是英国人  以前是收费的 售价249英镑 我曾经花了 ...

  8. nodejs的Express框架源码分析、工作流程分析

    nodejs的Express框架源码分析.工作流程分析 1.Express的编写流程 2.Express关键api的使用及其作用分析 app.use(middleware); connect pack ...

  9. laravel框架源码分析(一)自动加载

    一.前言 使用php已有好几年,laravel的使用也是有好长时间,但是一直对于框架源码的理解不深,原因很多,归根到底还是php基础不扎实,所以源码看起来也比较吃力.最近有时间,所以开启第5.6遍的框 ...

随机推荐

  1. SLC cache功能

    由于TLC需要多次编程,且未全部编程时wordLine处于不稳定状态,所以一般都会划出一部分区域作为SLC cache使用 SLC cache主要功能是,SSD接收到写命令后,先将数据写入SLC ca ...

  2. 论文阅读 | Universal Adversarial Triggers for Attacking and Analyzing NLP

    [code] [blog] 主要思想和贡献 以前,NLP中的对抗攻击一般都是针对特定输入的,那么他们对任意的输入是否有效呢? 本文搜索通用的对抗性触发器:与输入无关的令牌序列,当连接到来自数据集的任何 ...

  3. 安装部署FastDFS

    安装部署FastDFS 此篇博文是在安装好虚拟机和CentOS7的前提和转自以下几篇博客得来: 1.开启CentOS的网络连接:   1.1.网址:http://blog.csdn.net/white ...

  4. ESXi 制作模板并优化 Centos

    1.修改网络配置 vi /etc/sysconfig/network-scripts/ifcfg-eth0 #编辑network配置文件修改以下两项 (eth1同理) ONBOOT=yes BOOTP ...

  5. VUE 1.0

    现代开发模式:vue/react. 20%的时间花在了表现层 传统开发模式:jquery. 80%的时间花在了表现层 MVC——数据.表现.行为分离 视图层(表现层)<----->数据层 ...

  6. 第二章 impala基础使用

    第二章 impala基本使用 1.impala的使用 1.1.impala-shell语法 1.1.1.impala-shell的外部命令参数语法 不需要进入到impala-shell交互命令行当中即 ...

  7. 【LOJ】#3121. 「CTS2019 | CTSC2019」无处安放

    第一次有耐心去研究一道题答-- 以前看到题答要么扔要么就水能简单手玩出来的 1 2可以手玩出来,快乐! 4呢发现3 3比较格路,就把3 3都配了,一边带个4的除了4 4都塞满这么放进去,然后把一边带2 ...

  8. django form组件 cookies,session

    django form组件 渲染标签  就是组件里面的字段在前端展示叫做渲染标签 校验数据  用户输入的数据提交给后端组件叫做校验数据 forms组件中定义的字段都是必须传值的(required=Tr ...

  9. 解决Spring Boot集成Shiro,配置类使用Autowired无法注入Bean问题

    如题,最近使用spring boot集成shiro,在shiroFilter要使用数据库动态给URL赋权限的时候,发现 @Autowired 注入的bean都是null,无法注入mapper.搜了半天 ...

  10. Win32汇编常用算数指令

    汇编语言(assembly language)是一种用于电子计算机.微处理器.微控制器或其他可编程器件的低级语言,亦称为符号语言.在汇编语言中,用助记符(Mnemonics)代替机器指令的操作码,用地 ...