这是我参与「第四届青训营」笔记创作活动的第36天
初探Android网络请求框架之OkHttp3
一、Android 中的网络请求框架有哪些
Android 开发中,网络请求是无法避免的,但也可以不用它。
对于一个需要联网的 APP 来说,网络请求框架就是它的根基。
那网络请求框架有哪些呢?咱们往下看:
- HttpClient
- HttpURLConnection
- OkHttp
以上三个是底层网络请求框架,一般适用于
HTTP网络协议相关请求的。
往下看,还有封装的网络请求框架:
- Volley
- Retrofit
- Okgo
- Novate
这三个是基于底层网络请求框架进行的二次框架封装,一般都是用封装版框架。
比如 Volley 内部使用的是 HttpURLConnection 、HttpClient 、OkHttp ,
而 Retrofit 是直接基于 OkHttp 进行的封装,两者进行的封装也大有不同呢。
现在基本已经是 OkHttp + Retrofit 结合使用的天下了,他们的优势也是很明显的,Google 已经再 Android 4.4 之后将 HttpURLConnection 已经替换成了 OkHttp 。
发展史
Android 2.2 之前,HttpClient 是最佳选择,Android 2.2 之后,Google 官方建议使用 HttpURLConnection ,Android 6.0 以后,Google 官方移除了 HttpClient 相关的 API 。
简单对比:
| 框架 | OkHttp | Retrofit | Volley | android-async-http |
|---|---|---|---|---|
| 作者 | square 公司 | square 公司 | Google 公司 | Google 公司 |
| 性能 | 拥有Nio和Okio,所以性能更高,请求、处理速度更快。 io:阻塞式,nio:非阻塞式 | 代码简化,结构彻底,职责细分;易于和RxJava使用,使用方法较多,原理复杂。 | 可拓展性好,可支持HttpClient、HttpURLConnection、OkHttp。 | Android 5.0 之后已弃用。 |
| 场景 | 重量级网络交互场景:网络请求频繁,传输数据量大。 | --- | 传输数据量小;不能进行大数据的网络操作,比如音频文件的下载传输。 | --- |
| 缺点 | --- | --- | 致命缺点:不能下载大数据文件。 | 已停止维护。 |
经过上表的简单对比,能看出来 square 公司开发的 OkHttp ,Retrofit 框架是非常强大的。所以咱们这里说的是 OkHttp3~
二、OkHttp3 长什么样子
- 异步 GET 请求:
new OkHttpClient();- 构造
Request对象; - 通过前两步中的对象构建
Call对象; - 通过
Call#enqueue(Callback)方法来提交异步请求;
String url = "http://wwww.baidu.com";
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.get()// 默认就是GET请求,可以不写
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "onFailure: ");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d(TAG, "onResponse: " + response.body().string());
}
});
异步发起的请求会被加入到 Dispatcher 中的 runningAsyncCalls 双端队列中通过线程池来执行。
- 同步 GET 请求:
前面几个步骤和异步方式一样,只是最后一部是通过
Call#execute()来提交请求,注意这种方式会阻塞调用线程,所以在 Android 中应放在子线程中执行,否则有可能引起 ANR 异常,Android 3.0 以后已经不允许在主线程访问网络。
String url = "http://wwww.baidu.com";
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
Call call = okHttpClient.newCall(request);
new Thread(new Runnable() {
@Override
public void run() {
try {
Response response = call.execute();
Log.d(TAG, "run: " + response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
- POST 方式提交
String:
这种方式与前面的区别就是在构造 Request 对象时,需要多构造一个 RequestBody 对象,用它来携带我们要提交的数据。在构造 RequestBody 需要指定 MediaType ,用于描述请求 / 响应 body 的内容类型,关于 MediaType 的更多信息可以查看 RFC 2045,RequstBody 的几种构造方式:
MediaType mediaType = MediaType.parse("text/x-markdown; charset=utf-8");
String requestBody = "I am Purpleaf.";
Request request = new Request.Builder()
.url("https://api.github.com/markdown/raw")
.post(RequestBody.create(mediaType, requestBody))
.build();
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "onFailure: " + e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d(TAG, response.protocol() + " " + response.code() + " " + response.message());
Headers headers = response.headers();
for (int i = 0; i < headers.size(); i++) {
Log.d(TAG, headers.name(i) + ":" + headers.value(i));
}
Log.d(TAG, "onResponse: " + response.body().string());
}
});
我们大致看了看 OkHttp3 长什么样子,GET 的和 POST 的。
三、看一看 OkHttp3 整体流程
OkHttpClient实现Call.Factory,负责为Request创建Call。RealCall为具体的 Call 实现,其enqueue()异步接口通过Dispatcher利用ExecutorService实现,而最终进行网络请求时和同步execute()接口一致,都是通过RealCall中的getResponseWithInterceptorChain()函数实现。getResponseWithInterceptorChain()中利用Interceptor链条,分层实现缓存、透明压缩、网络 IO 等功能。
大概看一看即可,我们今天是来初探 OkHttp3 哒~ 别忘了哦!
四、总结
我们大致上预览了一遍,也简单对比了一下其他网络请求框架。可以看到 OkHttp3 的代码是比较简单的,多数为链式调用,对于开发者非常友好,但是内部封装逻辑过为复杂。然后通过上边的图片也大致过了一下它的整体过程,虽然现在一时半会儿看不懂,但是随着时光流逝,自身技术的提高,就会懂啦~
今天是青训营最后一天,祝同学们学习进步,马到成功哈!