网络框架解析与应用
第一章
网络框架完全解析与应用
第二章 网络框架出现背景及优势
http出现及发展
- 1960年由美国人Ted Nelson提出想法
- 由万维网协会(WWW)和互联网工程工作共同研究
- 目前使用最广泛的是HTTP1.1
- 如图所示
HTTP协议结构
-
请求头
- 表明本次请求的客户端
- 本次请求所使用的cookie
- 本次请求希望返回类型
- 本次请求是否采用数据压缩等等一系列设置
- 还可以自定义请求头
-
请求体
- 指定本次请求所使用的方法
- 主要用来携带本次请求的参数
-
响应头
- 服务器标识
- 状态码
- 内容编码
- cookie返回给客户端的cookie等等
-
响应体
- 主要就是我们的本次请求所返回的数据
-
工作流程
- 首先客户机与服务器需要建立连接
- 建立连接后,客户机发送一个请求给服务器
- 服务器接到请求后,给予相应的相应信息
- 客户端接收服务器所返回的信息,连接断开
-
HTTP优势
- 简单,快速
- 灵活
- 无连接
- 无状态
-
SPDY介绍(google)
SPDY是一种HTTP的兼容协议
多路复用请求
-
对请求划分优先级
可优先返回文字,多媒体内容后返回
压缩HTTP头
-
HTTP2.0
- 基于SPDY,IETF定制的新一代HTTP协议
- 更安全的SSL
-
okhttp
- 为我们android客户端支持HTTP2.0提供了途径
- 由著名的square团队开发
- 源码位置https://github.com/square/okhttp
-
okhttp优势
- 支持SPDY,HTTP2.0,共享同一个Socket来处理同一个服务器的所有请求
- 如果SPDY不可用,则通过连接池来减少请求延时
- 无缝的支持GZIP来减少数据流量
- 缓存响应数据来减少重复的网络请求
- 可以从很多的常用链接问题中自动恢复
- 使用起来非常简单
第三章 网络框架源码结构分析
网络框架源码结构
-
okhttp核心框架
-
总体设计
如图所示:
-
流程图
如图所示:
-
核心类图
如图所示:
-
多路复用机制
如图所示:
-
重连机制
如图所示:
-
-
okhttp核心类(粗体为核心流程)
- Route
路由类:用来分发请求 - ResponseBody
响应实体类:存放返回的数据,在byte()方法中是最原始的字节数据 - Response
构建者模式的响应类- Headers headers
所有的响应头 - ResponseBody body
响应体
- Headers headers
- RequestBody
请求类体类- FormBody
请求头 - MultipartBody
文件上传等
- FormBody
- Request
构建者模式的请求类 - Call(Interface)
请求任务
HttpEngine engine - RealCall(Runnable) Call的实现类
真正执行响应处理
Callback callback - HttpUrl
Url的工具类 - Headers
请求头 - Dns
解析域名 - ConnectionPool
连接池 -
CallBack
回调 - Cache、ChchePoll
缓存模块 -
HttpEngine
真正发送请求的类- sendRequest 发送请求
- recover重连
- Dispatcher
分发- executed(RealCall call)
-
HttpClient
- Dispatcher dispatcher
- Route
网络框架简单使用
- 简单实现get、post请求
-
// gradle引用
compile 'com.squareup.okhttp3:okhttp:3.4.2'
-
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.thssh.okhttpstudy.MainActivity"> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/tv_content" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Hello World!" /> </ScrollView> <Button android:id="@+id/btn_post" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:clickable="true" android:text="post" /> <Button android:id="@+id/btn_get" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/btn_post" android:layout_alignParentRight="true" android:layout_marginBottom="10dp" android:clickable="true" android:text="get" /> </RelativeLayout>
-
MainActivity.java
public class MainActivity extends AppCompatActivity { @Bind(R.id.btn_get)Button btnGet; @Bind(R.id.btn_post)Button btnPost; @Bind(R.id.tv_content)TextView tvContent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); } @OnClick(R.id.btn_get) public void getRequest(){ Request request = new Request.Builder() .url("http://www.baidu.com").build(); OkHttpClient client = new OkHttpClient(); Call call = client.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { setText(e.getMessage()); } @Override public void onResponse(Call call, Response response) throws IOException { setText(response.body().string()); } }); } @OnClick(R.id.btn_post) public void postRequest(){ OkHttpClient client = new OkHttpClient(); FormBody.Builder form = new FormBody.Builder(); form.add("userName", "hutianhang@docmail.cn"); form.add("password", "a123456"); form.add("clienttype", "mobile"); Request req = new Request.Builder() .url("http://mail.docmail.cn/auth/login") .post(form.build()) .build(); Call call = client.newCall(req); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { setText(e.getMessage()); } @Override public void onResponse(Call call, Response response) throws IOException { setText(response.body().string()); } }); } private void setText(final String text){ tvContent.post(new Runnable() { @Override public void run() { tvContent.setText(text); } }); } }
-
封装通用网络模块
- 为什么要封装通用网络模块
- 强大的可复用性
- 与业务逻辑完全隔离
- 强大的可扩展性
- 封装思路
- 封装一个公共的OkHttpClient
- 封装一个通用的请求创建类CommonRequest
- 封装一个通用的响应解析类JsonCommonRequest
- 文件下载封装
- 代码实战通用网络模块封装
- 使用我们的网络模块
- 为什么要封装通用网络模块
-
第四章 利用网络框架封装一个通用的网络请求模块
通用网络框架封装(详见源码)
第五章 使用封装好的网络模块
使用实例(详见源码)
第六章 总结
网络框架完全解析与应用
- HTTP发展及okhttp优势
- okhttp源码解析及基础用法
- 基于okhttp封装通用网络模块