android开发网络框架OkHttp
OkHttp
本文属于android网络编程课程里的系列文章之一
详情请查看网络编程课程
前面我们学习了http协议,然后使用java的api去访问网络,需要准备请求头,设置好各种东西,自己处理线程。会不会很麻烦呢?
于是,很多前辈觉得这样子很麻烦,就把这些复杂的东西封装起来,我们通过简单的调用,就可以实现网络请求了。
优点的话去看官网吧,这里就写成中文的了
- 请求同一主机的时候,一般是指同一域名,支持共享同一个socket
- 通过连接池减少请求延时
- 传输通过GZIP压缩,减少下载内容的体积
- 用缓存的方式避免重复的请求
应用场景
学习一门技术,从应用场景上手是最快的。毕竟你要落实到用处的嘛。
OkHttp在我们android开发中有哪些使用场景呢?
- 请求内容数据(目前来说,数据格式主要是json,xml比较少用了)
- 加载图片(一般来说,图片地址以内容的形式返回到手机端,然后再通过图片地址进行加载到控件中)
- 上传文件/数据(头像的上传,采集数据的上传,甚至是录像之类的大文件上传)
使用
api文档
这里我们使用到的api文档是商城的api文档
后面我们也会开放更多的文档
关于高版本(27以上)http访问的配置
如果访问为https协议的话,略过即可
如果在android27以上,默认是不支持Http访问的了,需要使用https,如果你要使用Http明文访问,那么需要配置一下。
在清单文件,application节点,添加
android:networkSecurityConfig="@xml/network_security_config"
network_security_config
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config>
<domain includeSubdomains="true">sunofbeaches.com</domain>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">www.sunofbeach.net</domain>
<domain includeSubdomains="true">imgs.sunofbeaches.com</domain>
</domain-config>
</domain-config>
</network-security-config>
关于网络安全配置文件的说明请看这篇文章
声明权限
<uses-permission android:name="android.permission.INTERNET" />
添加依赖
implementation("com.squareup.okhttp3:okhttp:4.2.2")
异步get请求
步骤:
- 创建OkHttpClient
- 创建请求内容
- 浏览器根据请求内容创建请求任务
- 执行请求任务
代码:
public void asyncGet(View view) {
//获取商城的分类信息
String url = "https://www.sunofbeach.net/shop/api/discovery/categories";
//1、创建client,理解为创建浏览器
OkHttpClient okHttpClient = new OkHttpClient();
//2、创建请求内容
Request request = new Request.Builder()
.url(url)
.get()
.build();
//3、用浏览器创建调用任务
Call call = okHttpClient.newCall(request);
//4、执行任务
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call,@NotNull IOException e) {
Log.d(TAG,"onFailure -- > " + e.toString());
}
@Override
public void onResponse(@NotNull Call call,@NotNull Response response) throws IOException {
Log.d(TAG,"response -- > " + response.body().string());
}
});
}
执行结果:
同步的get请求
步骤跟前面一样,只是在执行任务的时候,不是异步的。
同步的请求,需要自己处理线程的问题,不可以在UI线程去执行任务。
代码
public void syncGet(View view) {
//获取商城的分类信息
String url = "https://www.sunofbeach.net/shop/api/discovery/categories";
//1、创建client,理解为创建浏览器
OkHttpClient okHttpClient = new OkHttpClient();
//2、创建请求内容
Request request = new Request.Builder()
.url(url)
.get()
.build();
//3、用浏览器创建调用任务
final Call call = okHttpClient.newCall(request);
//4、执行任务
new Thread(new Runnable() {
@Override
public void run() {
try {
Response response = call.execute();
Log.d(TAG,"response -- > " + response.body().string());
} catch(IOException e) {
e.printStackTrace();
Log.d(TAG,"failure -- > " + e.toString());
}
}
}).start();
}
post请求
++举一反三呀++,对吧!前面get请求,在创建请求的时候.get(),那么post呢?
我们也有post请求的方法
测试一下商城的搜索接口
https://www.sunofbeach.net/shop/api/search/page
page是页码
参数:keyword
public void doSearch(View view) {
String url = "https://www.sunofbeach.net/shop/api/search/1";
RequestBody requestBody = new FormBody.Builder()
.add("keyword","电脑")
.build();
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call,@NotNull IOException e) {
Log.d(TAG,"onFailure -- > " + e.toString());
}
@Override
public void onResponse(@NotNull Call call,@NotNull Response response) throws IOException {
Log.d(TAG,"response json --> " + response.body().string());
}
});
}
可以看到,上面requestBody是FormBody,我们看看RequestBody的继承关系:
除了表单数据以外,还可以是文件。
学习神器SOBAndroidMiniWeb
程序地址:
具体的使用方法请看里面的文档说明。有了这个神器,我们就可以做接下来的网络学习了。
post上传单文件
使用场景:
比如说我们上传头像,比如说我们上传log
权限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
一般来说, 我们读取的数据在扩展卡里,所以要加上这个权限。
比如说我们上传一张图片试试看。之前我们不是有imagePicker嘛,同学们可以结合那个案例去整一个,我这里为了比较快一点,我就直接复制一张图片到特定目录下了。
关于读取图片的动态权限获取请看这里:
public void postFile(View view) {
String url = "https://10.0.2.2:9102/file/upload";
OkHttpClient httpClient = new OkHttpClient.Builder().build();
File file = new File("/storage/emulated/0/Download/1.jpg");
MediaType mediaType = MediaType.parse("image/jpeg");
RequestBody fileBody = RequestBody.create(file,mediaType);
RequestBody requestBody = new MultipartBody.Builder()
.addFormDataPart("file",file.getName(),fileBody)
.build();
Request request = new Request.Builder().url(url).post(requestBody).build();
Call call = httpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call,@NotNull IOException e) {
Log.d(TAG,"上传失败--> " + e.toString());
}
@Override
public void onResponse(@NotNull Call call,@NotNull Response response) throws IOException {
Log.d(TAG,"上传结果:" + response.body().string());
}
});
}
类型可以查看这里
上传结果:
{"success":true,"code":10000,"message":"上传成功.文件路径为:E:\\sobCourse\\sobAndroidWeb\\SOBAndroidMiniWeb\\sobUpload\\1.jpg","data":null}
查看路径上的图片:
多文件上传
那如何上传多文件呢?
在web程序里,我定义的接口
/file/upload
为单文件上传 而多文件上传的接口为 参数Kye为:file
/files/upload
为多文件上传 参数key为 files
上传代码:
public void postMultiFile(View view) {
String url = "https://10.0.2.2:9102/files/upload";
OkHttpClient httpClient = new OkHttpClient.Builder().build();
File fileOne = new File("/storage/emulated/0/Download/1.jpg");
File fileTwo = new File("/storage/emulated/0/Download/rBsADV3nxtKACoSfAAAPx8jyjF8169.png");
File fileThree = new File("/storage/emulated/0/Download/rBsADV2rEz-AIzSoAABi-6nfiqs456.png");
MediaType mediaType = MediaType.parse("image/jpeg");
RequestBody fileOneBody = RequestBody.create(fileOne,mediaType);
RequestBody fileTwoBody = RequestBody.create(fileTwo,mediaType);
RequestBody fileThreeBody = RequestBody.create(fileThree,mediaType);
RequestBody requestBody = new MultipartBody.Builder()
.addFormDataPart("files",fileOne.getName(),fileOneBody)
.addFormDataPart("files",fileTwo.getName(),fileTwoBody)
.addFormDataPart("files",fileThree.getName(),fileThreeBody)
.build();
Request request = new Request.Builder().url(url).post(requestBody).build();
Call call = httpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call,@NotNull IOException e) {
Log.d(TAG,"多文件上传失败--> " + e.toString());
}
@Override
public void onResponse(@NotNull Call call,@NotNull Response response) throws IOException {
Log.d(TAG,"多文件上传结果:" + response.body().string());
}
});
}
结果:
{"success":true,"code":10000,"message":"上传成功3个文件,路径:E:/sobCourse/sobAndroidWeb/SOBAndroidMiniWeb/sobUpload","data":null}
好啦,学习android知道这些基本上够用了。知道怎么请求数据,怎么样上传数据。任务就这两个。
至于下载那些也是一样的,本质还是一个请求任务,而内容则在response里头,读取出来写入文件即可。这些我们都会在后面的案例里有。同学们先掌握这些先。代码一定要写。如果遇到问题,就发帖子交流吧。