最近在改项目的时候发现以前的项目网络请求框架是XUtils,这在过去是一个比较流行的框架,功能强大而且比较全面,但是就XUtils本身的网络请求模块而言,因为Google在android6.0中已经将HttpClient部分给删除,当我把开发工具的compileSdkVersion调到23以上,该框架就会出错,Volley这个框架也是一样,内部也是HttpClient和HttpUrlConnection实现的,所以如果你的项目中还是用了这些古老的框架,还是赶紧换吧。
2.1 集成:
androidstudio直接在gradle中添加:
dependencies
{
compile ‘com.squareup.okhttp3:okhttp:3.5.0’
}
在manifest中添加网络权限。
2.2 使用类型:
2.2.1 Get方式:
步骤: new OkHttpClient ()
Request.Builder方便添加header
call.enqueue异步执行
//get请求方式
private void httpGet() {
String url="http://www.baidu.com";
//client对象,核心类
OkHttpClient client=new OkHttpClient();
//构建者模式,url地址,get方式,
// final Request request=new Request.Builder().url(url).get().build();
//用requestBuilder可以添加header
Request.Builder requestBuilder = new Request.Builder().url(url);
requestBuilder.addHeader("key","value")
Request request=requestBuilder.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//子线程中
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String str=response.body().string();
//子线程中,response.body()中既可以获取String,也可以获取成byte数组,或者是stream
}
});
}
注意:callback中的failure和success的方法都是在非ui线程中,如果涉及到控件的刷新,一定要在主线程中进行处理。
OkHttp的添加header有两种方式:
使用 header(name,value) 来设置HTTP头的唯一值,相同的key值会覆盖
使用 addHeader(name,value) 来补充新值,不会覆盖相同的key值
使用 header(name) 读取唯一值或多个值的最后一个值
使用 headers(name) 获取所有值
2.2.2 表单提交(key-value形式)
//键值对参数提交(表单提交)
private void httpPost() {
String url="";
//client对象,核心类
OkHttpClient client=new OkHttpClient();
//构建者模式,url地址,get方式,
// final Request request=new Request.Builder().url(url).get().build();
//这里面添加参数
RequestBody requestbody=new FormBody.Builder()
.add("key1","param1")
.add("key2","param2")
.build();
//用requestBuilder可以添加header
Request.Builder requestBuilder = new Request.Builder().url(url).post(requestbody);
requestBuilder.addHeader("key","value");
Request request=requestBuilder.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//子线程中
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String str=response.body().string();
//子线程中
}
});
}
2.2.3请求体是一个JSON格式的数据
private void httpPostJson() {
String url="";
//client对象,核心类
OkHttpClient client=new OkHttpClient();
//这里面添加参数
Map<String,String> map=new HashMap<>();
map.put("key1","param1");
map.put("key2","param2");
map.put("key3","param3");
//这里用的是fastjson进行解析的
String jsonstr= JSON.toJSONString(map);
RequestBody requestbody = RequestBody.create(MediaType.parse("application/json"), jsonstr);
//用requestBuilder可以添加header
Request.Builder requestBuilder = new Request.Builder().url(url).post(requestbody);
requestBuilder.addHeader("key","header1");
Request request=requestBuilder.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//子线程中
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String str=response.body().string();
//子线程中
}
});
}
post的代码也比较简单,相信大家肯定能都看懂。但是在这里面涉及到一个比较重要的类MediaType,该类来指定post上传的参数类型。
FormBody涉及常见的有三种:
application/x-www-form-urlencoded 数据是个普通表单
multipart/form-data 数据里有文件
application/json 数据是个json
但是好像以上的普通表单并没有指定MediaType,这是因为FormBody继承了RequestBody,它已经指定了数据类型为application/x-www-form-urlencoded。
2.2.4 上传file文件(以图片为例)
//文件的上传
private void httpFileUp() {
OkHttpClient client = new OkHttpClient();
final MediaType MEDIA_TYPE_TEXT = MediaType.parse("image/png");
File file=new File("wy.png");
MultipartBody multipartBody=new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file",file.getName(),RequestBody.create(MEDIA_TYPE_TEXT,file))
.build();
Request request = new Request.Builder()
.url("http://www.baidu.com")
.post(multipartBody)
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
}
对于文件上传,我们用RequestBody的另一个继承类MultipartBody,该类首先需要setType,这里面的参数参有五种类型:
public static final MediaType MIXED = MediaType.parse("multipart/mixed");
public static final MediaType ALTERNATIVE = MediaType.parse("multipart/alternative");
public static final MediaType DIGEST = MediaType.parse("multipart/digest");
public static final MediaType PARALLEL = MediaType.parse("multipart/parallel");
public static final MediaType FORM = MediaType.parse("multipart/form-data");
源码中有相应的解释,当为FORM时,`final MediaType MEDIA_TYPE_TEXT = MediaType.parse(“image/png”);这行代码的类型指定参数可以参考:点击查看,如果接口没有file字段,直接上传文件,可以这样写:.post(RequestBody.create(MEDIA_TYPE_TEXT, file))
2.2.5 下载文件:
private void httpFileDown() {
OkHttpClient mOkHttpClient = new OkHttpClient();
String url = "";
Request request = new Request.Builder().url(url).build();
mOkHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) {
InputStream inputStream = response.body().byteStream();
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(new File("/sdcard/wy.jpg"));
byte[] buffer = new byte[2048];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, len);
}
fileOutputStream.flush();
} catch (IOException e) {
}
}
});
}
文件下载比较简单,其实就是一个get请求,获取到数据流后写进文件中即可。
总结:熟悉以上方法后,我们基本上能够应对android开发中的网络请求了,但是很明显,项目中的接口有很多,每次这样写肯定费事,而且OkHttpClient 一般一个项目中只需要一个全局对象,并且相关的参数比如参数,缓存也没有设置,所以这篇博客权当入门使用,感兴趣的可以看我的下一篇,Android网络请求框架—-Okhttp3完全解析(2),封装框架。