自学了视频的内容,整理成笔记,方便查阅和复习。
OKHttp
简介
OKHttp是一款高效的HTTP客户端,支持连接同一地址的链接共享同一个socket,通过连接池来减小响应延迟,还有透明的GZIP压缩,请求缓存等优势,其核心主要有路由、连接协议、拦截器、代理、安全性认证、连接池以及网络适配,拦截器主要是指添加,移除或者转换请求或者回应的头部信息。这个库也是square开源的一个网络请求库(okhttp内部依赖okio)。
下载地址:http://square.github.io/okhttp/
1、可在上面下载 :
2、或在build.gradle中添加:
compile 'com.squareup.okhttp3:okhttp:3.4.1'
在AndroidManifest.xml文件添加网络访问:
<uses-permission android:name="android.permission.INTERNET"/>
OkHttp主要功能:
1、联网请求文本数据
2、大文件下载
3、大文件上传
4、请求图片
首先写好布局和代码:
布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.atguigu.android.atguigu.activity.OkhttpAcyivity"
android:orientation="vertical">
<Button
android:id="@+id/get"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="get请求"/>
<Button
android:id="@+id/post"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="post请求"/>
<Button
android:id="@+id/get_utils"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="get_utils请求"/>
<Button
android:id="@+id/post_utils"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="post_utils请求"/>
<Button
android:id="@+id/downloadfile"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="使用post_utils下载文件"/>
<Button
android:id="@+id/uploadfile"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="使用post_utils上传文件"/>
<Button
android:id="@+id/getimage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="使用post_utils请求单张图片"/>
<ProgressBar
android:id="@+id/pb"
style="?android:progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="显示数据"
android:textSize="20sp"
/>
</LinearLayout>
点击事件:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.okhttp_acyivity);
get = (Button)findViewById(R.id.get);
text = (TextView) findViewById(R.id.text);
post = (Button)findViewById(R.id.post);
get_utils = (Button)findViewById(R.id.get_utils);
post_utils = (Button)findViewById(R.id.post_utils);
downloadfile = (Button)findViewById(R.id.downloadfile);
pb = (ProgressBar)findViewById(R.id.pb);
uploadfile = (Button)findViewById(R.id.uploadfile);
getimage = (Button)findViewById(R.id.getimage);
image = (ImageView)findViewById(R.id.image);
get.setOnClickListener(this);
post.setOnClickListener(this);
get_utils.setOnClickListener(this);
post_utils.setOnClickListener(this);
downloadfile.setOnClickListener(this);
uploadfile.setOnClickListener(this);
getimage.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.get://get请求
//分线程
new Thread(){
@Override
public void run() {
super.run();
//获取数据
getDataFronGet();
}
}.start();
break;
case R.id.post://post请求
//分线程
new Thread(){
@Override
public void run() {
super.run();
//获取数据
getDataFronPost();
}
}.start();
break;
case R.id.get_utils://使用okhttp-utils get请求
getDataByOkhttputils();
break;
case R.id.post_utils:
postDataByOkhttputils();//使用okhttp-utils post请求
break;
case R.id.downloadfile://使用okhttp-utils 下载文件
downloadFile();
break;
case R.id.uploadfile://使用okhttp-utils 上传文件
multiFileUpload();
break;
case R.id.getimage://请求单张图片
image();
break;
}
}
GET请求
使用get请求网络数据:
private void getDataFronGet() {
try {
String result = get("http://api.m.mtime.cn/PageSubArea/TrailerList.api");
Log.w(TAG,result);
Message msg = Message.obtain();
msg.what = GET;
msg.obj = result;
//主线程更新数UI
handler.sendMessage(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
get请求:
OkHttpClient client = new OkHttpClient();
private String get(String url) throws IOException {
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
POST请求
使用post请求网络数据:
private void getDataFronPost() {
try {
String result = post("http://api.m.mtime.cn/PageSubArea/TrailerList.api","");
Log.w(TAG,result);
Message msg = Message.obtain();
msg.what = POST;
msg.obj = result;
//主线程更新数UI
handler.sendMessage(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
post请求:
private String post(String url,String json) throws IOException {
RequestBody body = RequestBody.create(JSON,json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
更新UI,显示文本:
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case GET:
text.setText((String)msg.obj);
case POST:
text.setText("");
text.setText((String)msg.obj);
break;
}
}
};
OKHttp_Utils 简介
下载:https://github.com/hongyangAndroid/okhttp-utils
import Module
运行后会出现一些错误,解决报错:
1、在okhttp-utils的build.gradle文件中注射掉一下代码
//apply plugin: 'com.novoda.bintray-release'//添加
添加
//publish {
// userOrg = 'hongyangandroid'//bintray.com用户名
// groupId = 'com.zhy'//jcenter上的路径
// artifactId = 'okhttputils'//项目名称
// publishVersion = '2.6.2'//版本号
// desc = 'Oh hi, this is a nice description for a project, right?'
// website = 'https://github.com/hongyangAndroid/okhttp-utils'
//}
//
2、在sample-okhttp中的build.gradle文件中配置:
allprojects {
repositories {
maven { url "https://jitpack.io" }
}
}
把okhttp-utils集成到我们项目中
右键app --> Open Module Settings -->Dependencies -->右边+号 -->选择Module dependency -->选择okhttp-utils
解决报错:
1、在我们的项目的build.gradle文件中关联库
implementation project(':okhttputils')
2、因为okhttputils库里面本身就有okhttp库和okio库,需要在我们项目的build.gradle文件中注释掉以下代码
// implementation files('libs/okhttp-3.4.1.jar')
// implementation files('libs/okio-1.9.0.jar')
OKHttp 使用 Utils 的 GET 请求文本
public void getDataByOkhttputils()
{
String url = "http://www.zhiyun-tech.com/App/Rider-M/changelog-zh.txt";
url="http://api.m.mtime.cn/PageSubArea/TrailerList.api";
OkHttpUtils.get()
.url(url)
.id(100)
.build()
.execute(new MyStringCallback());
}
public class MyStringCallback extends StringCallback
{
@Override
public void onBefore(Request request, int id)
{
setTitle("loading...");
}
@Override
public void onAfter(int id)
{
setTitle("Sample-okHttp");
}
@Override
public void onError(Call call, Exception e, int id)
{
e.printStackTrace();
text.setText("onError:" + e.getMessage());
}
@Override
public void onResponse(String response, int id)
{
Log.e(TAG, "onResponse:complete");
text.setText("onResponse:" + response);
switch (id)
{
case 100:
Toast.makeText(OkhttpAcyivity.this, "http", Toast.LENGTH_SHORT).show();
break;
case 101:
Toast.makeText(OkhttpAcyivity.this, "https", Toast.LENGTH_SHORT).show();
break;
}
}
@Override
public void inProgress(float progress, long total, int id)
{
Log.e(TAG, "inProgress:" + progress);
// mProgressBar.setProgress((int) (100 * progress));
}
}
OKHttp 使用 Utils 的 POST 请求文本
public void postDataByOkhttputils()
{
String url = "http://www.zhiyun-tech.com/App/Rider-M/changelog-zh.txt";
url="http://api.m.mtime.cn/PageSubArea/TrailerList.api";
OkHttpUtils
.post()
.url(url)
.id(100)
.build()
.execute(new MyStringCallback());
}
OKHttp 使用 Utils下载大文件
public void downloadFile()
{
String url = "http://vfx.mtime.cn/Video/2016/07/24/mp4/160724154733643806.mp4";
OkHttpUtils//
.get()//
.url(url)//
.build()//
.execute(new FileCallBack(Environment.getExternalStorageDirectory().getAbsolutePath(), "test.mp4")//
{
@Override
public void onBefore(Request request, int id)
{
}
@Override
public void inProgress(float progress, long total, int id)
{
pb.setProgress((int) (100 * progress));
Log.e(TAG, "inProgress :" + (int) (100 * progress));
}
@Override
public void onError(Call call, Exception e, int id)
{
Log.e(TAG, "onError :" + e.getMessage());
}
@Override
public void onResponse(File file, int id)
{
Log.e(TAG, "onResponse :" + file.getAbsolutePath());
}
});
}
在手机上播放:
OKHttp 使用 Utils 进行文件的上传
搭好服务器之后,上传文件
public void multiFileUpload()
{
String mBaseUrl = "http://192.168.35.11:8080/FileUpload/FileUploadServlet";
File file = new File(Environment.getExternalStorageDirectory(), "a.png");
File file2 = new File(Environment.getExternalStorageDirectory(), "c.png");
if (!file.exists())
{
Toast.makeText(OkhttpAcyivity.this, "文件不存在,请修改文件路径", Toast.LENGTH_SHORT).show();
return;
}
Map<String, String> params = new HashMap<>();
params.put("username", "张鸿洋");
params.put("password", "123");
String url = mBaseUrl;
OkHttpUtils.post()//
.addFile("mFile", "aa.png", file)//
.addFile("mFile", "cc.png", file2)//
.url(url)
.params(params)//
.build()//
.execute(new MyStringCallback());
}
OKHttp 使用 Utils 请求单张图片
public void image()
{
text.setText("");
String url = "http://images.csdn.net/20150817/1.jpg";
OkHttpUtils
.get()//
.url(url)//
.tag(this)//
.build()//
.connTimeOut(20000)
.readTimeOut(20000)
.writeTimeOut(20000)
.execute(new BitmapCallback()
{
@Override
public void onError(Call call, Exception e, int id)
{
text.setText("onError:" + e.getMessage());
}
@Override
public void onResponse(Bitmap bitmap, int id)
{
Log.e("TAG", "onResponse:complete");
image.setImageBitmap(bitmap);
}
});
}
OKHttp 其他封装库
封装了okhttp的网络框架,支持大文件上传下载,上传进度回调,下载进度回调,表单上传(多文件和多参数一起上传),链式调用,可以自定义返 回对象,支持Https和自签名证书,支持cookie自动管理,支持四种缓存模式缓存网络数据,支持301、302重定向,扩展了统一的上传管理和下载管理功能。
下载连接:https://github.com/jeasonlzy/okhttp-OkGo
OKHttp 源码分析
一、应用层:
1、 将请求添加到分发器中 client.dispatcher().executed(this);
2、 创建截获器 ApplicationInterceptorChain(对请求进行压缩、修改编码等处理)
二、逻辑层
1、数据缓存:
发送请求sendRequest()之前对数据进行缓存处理。
(1)缓存的数据没有过期,直接使用
(2)缓存的数据过期,先用过期的,然后再去网络请求数据,并更新本地数据
(3)缓存的数据没有,去网络直接获取
2、底层使用连接池
连接 connect() --> 创建一个流newStream() --> 找到一个好的连接findHealthyConnection() --> 在线程池中查找好的连接findConnection() --> 连接池connectPool --> 发现连接池中有可用的连接 pooledConnection
3、路线选择器
如果连接池中没有可用的,先从路径选择(routeSelector)中查找 --> 如果在路线选择器没有找到 --> 创建新的连接newConnection
4、网络截获器可以有多个
读取答复 readResponse() --> 创建网络截获器NetworkInterceptorChain(),递归实现 --> 应答 engine.getResponse() --> 没有重定向直接返回 --> 如果有重定向,再次创建截获器 --> 截获器可以有多个,取决于是否有重定向
三、链路层
1、底层是 socket
连接connectSocket() --> 拿source 读数据 --> 拿sink写数据
根据用户的请求Request放入到指定队列,并使用拦截器链的方式去执行我们的请求操作。