您的位置:首页 > 理论基础 > 计算机网络

android okhttp3框架使用

2017-11-24 16:54 369 查看
今天总结下OKhttp3框架的一些功能,其实现在很多可能不直接用okhttp3了,用的是retrofit,它其实并不是一个网络框架,而是对okhttp3进行了更好的封装,方便调用,底层网络这块用的还是okhttp3,所以又必要学习下okhttp3的使用。

okhttp3功能很丰富,有同步,异步,文件下载,上传,请求头,cookie等一系列

同步请求

关于请求的一些什么超时等,都是封装在OkHttpClient类中,这是一个全局的发送请求的,okhttp3框架中所有的请求,都是封装在Request中,包括请求方式,请求添加url,请求添加头部信息,请求设置相关tag,这是和取消请求有关系.Request中使用了Builder模式,

Request request = new Request.Builder()
.url(url)
.get()
.addHeader("aa","aa")
.build();

其实一个Request请求封装了,okhttp3包括了所有的请求方式
public Builder get() {
return method("GET", null);
}

public Builder head() {
return method("HEAD", null);
}

public Builder post(RequestBody body) {
return method("POST", body);
}

public Builder delete(@Nullable RequestBody body) {
return method("DELETE", body);
}

public Builder delete() {
return delete(Util.EMPTY_REQUEST);
}

public Builder put(RequestBody body) {
return method("PUT", body);
}

public Builder patch(RequestBody body) {
return method("PATCH", body);
}

现在我们发送一个get同步请求:
String url = "https://www.baidu.com/";
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.get()
.build();
Call call = okHttpClient.newCall(request);
try {
Response response = call.execute();
if(null!=response&&response.isSuccessful()&&response.code()==200){
Log.e(TAG,"content="+response.body().string());
}
} catch (IOException e) {
e.printStackTrace();
}

发现报错了:

 Caused by: android.os.NetworkOnMainThreadException

这是说在4.0以后不能在主线程中发送网络请求,所以我们要开启一个子线程中发送了,

结果:



结果是请求ok了,但是我们其实实际开发中很少用到同步请求了,大部分都用是异步,

异步请求

OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url("https://www.baidu.com/").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 {
if(null!=response&&response.isSuccessful()){
Log.e(TAG,"content="+response.body().string());
}
}
});


okhttp3请求返回不是说给我们返回一个string字符串,因为你下载返回肯定不是一个string啊,看下response.body()返回有那么值就知道了:



如果是下载文件就是返回一个byte[] 或者byteStream流,如果是一个普通的请求就返回一个string了,后面会整合Gson,封装一个工具类,可以直接使用,把json转成一个Model给上层调用.

下面讲的都是以异步请求为主,这些都是不带请求参数的,那么如果带请求参数的怎么传递参数呢?
异步请求带参数

OkHttpClient client = new OkHttpClient();
HttpUrl httpUrl =  HttpUrl.parse("http://bz.budejie.com/?typeid=2&ver=3.4.3&no_cry=1&client=android&c=wallPaper&a=wallPaperNew&index=1&size=60&bigid=0").newBuilder().addQueryParameter("name","zhouguizhi").build();
Request request = new Request.Builder().url(httpUrl).get().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 {
if(null!=response&&response.isSuccessful()){
Log.e(TAG,"content="+response.body().string());
}
}
});

上面的url地址,是我在网上随便找了一个地址,就带了一个请求参数name,请求返回log:

11-24 00:42:58.899 14125-14525/com.simple E/MainActivity: content={"code":"E00000000","msg":"\u64cd\u4f5c\u6210\u529f\u3002","data":{"TotalCount":"80089","WallpaperListInfo":[{"ID":10983957,"PicName":"10983957.jpg","pic_path":"\/picture1\/M00\/0E\/8B\/wKiFQ1Osx3GAOttdAAF3dCmTv6k397.jpg","BigCategoryId":1040,"SecondCategoryId":2132,"CreateTime":"2014-06-27
09:21:24","passtime":"2016-06-05 11:54:49","UserName":"sprit_admin","DownloadCount":2721,"GoodCount":2730,"tags":"\u7238\u7238\u56de\u6765\u4e86","WallPaperMiddle":"http:\/\/bzpic.spriteapp.cn\/250x445\/picture1\/M00\/0E\/8B\/wKiFQ1Osx3GAOttdAAF3dCmTv6k397.jpg","WallPaperBig":"http:\/\/bzpic.spriteapp.cn\/1080x1920\/picture1\/M00\/0E\/8B\/wKiFQ1Osx3GAOttdAAF3dCmTv6k397.jpg","WallPaperDownloadPath":"http:\/\/bzpic.spriteapp.cn\/1080x1920\/picture1\/M00\/0E\/8B\/wKiFQ1Osx3GAOttdAAF3dCmTv6k397.jpg","WallPaperSource":"http:\/\/bzpic.spriteapp.cn\/744x1392\/picture1\/M00\/0E\/8B\/wKiFQ1Osx3GAOttdAAF3dCmTv6k397.jpg","weixin_url":"http:\/\/www.budejie.com\/bz\/bdj-10983957.html?wx.qq.com"},{"ID":10984612,"PicName":"10984612.jpg","pic_path":"\/picture1\/M00\/0E\/AA\/wKiFR1O08hCAfBH0AAK8jGL8Pi4655.jpg","BigCategoryId":1040,"SecondCategoryId":2629,"CreateTime":"2014-07-03
14:00:59","passtime":"2016-06-05 11:52:31","UserName":"173694","DownloadCount":2750,"GoodCount":2760,"tags":"\u5e05\u54e5 \u674e\u79c0\u8d6b \u674e\u8d6b\u79c0","WallPaperMiddle":"http:\/\/bzpic.spriteapp.cn\/250x445\/picture1\/M00\/0E\/AA\/wKiFR1O08hCAfBH0AAK8jGL8Pi4655.jpg","WallPaperBig":"http:\/\/bzpic.spriteapp.cn\/1080x1920\/picture1\/M00\/0E\/AA\/wKiFR1O08hCAfBH0AAK8jGL8Pi4655.jpg","WallPaperDownloadPath":"http:\/\/bzpic.spriteapp.cn\/1080x1920\/picture1\/M00\/0E\/AA\/wKiFR1O08hCAfBH0AAK8jGL8Pi4655.jpg","WallPaperSource":"http:\/\/bzpic.spriteapp.cn\/744x1392\/picture1\/M00\/0E\/AA\/wKiFR1O08hCAfBH0AAK8jGL8Pi4655.jpg","weixin_url":"http:\/\/www.budejie.com\/bz\/bdj-10984612.html?wx.qq.com"},{"ID":10781820,"PicName":"10781820.jpg","pic_path":"\/picture2\/M00\/07\/2E\/wKiFRlNYdQCAA5KFAAIX6TJTu3w941.jpg","BigCategoryId":1040,"SecondCategoryId":2629,"CreateTime":"2014-04-24
10:17:05","passtime":"2016-06-05 11:45:47","UserName":"135514","DownloadCount":2755,"GoodCount":2772,"tags":"\u5e05\u54e5","WallPaperMiddle":"http:\/\/bzpic.spriteapp.cn\/250x445\/picture2\/M00\/07\/2E\/wKiFRlNYdQCAA5KFAAIX6TJTu3w941.jpg","WallPaperBig":"http:\/\/bzpic.spriteapp.cn\/1080x1920\/picture2\/M00\/07\/2E\/wKiFRlNYdQCAA5KFAAIX6TJTu3w941.jpg","WallPaperDownloadPath":"http:\/\/bzpic.spriteapp.cn\/1080x1920\/picture2\/M00\/07\/2E\/wKiFRlNYdQCAA5KFAAIX6TJTu3w941.jpg","WallPaperSource":"http:\/\/bzpic.spriteapp.cn\/744x1392\/picture2\/M00\/07\/2E\/wKiFRlNYdQCAA5KFAAIX6TJTu3w941.jpg","weixin_url":"http:\/\/www.budejie.com\/bz\/bdj-10781820.html?wx.qq.com"},{"ID":10983477,"PicName":"10983477.jpg","pic_path":"\/picture2\/M00\/0A\/34\/wKiFWVOnjOKAG256AAF-TNkxjfk670.jpg","BigCategoryId":1056,"SecondCategoryId":2779,"CreateTime":"2014-06-23
10:10:01","passtime":"2016-06-05 11:42:20","UserName":"168844","DownloadCount":11359,"GoodCount":11369,"tags":"MYOTEE \u840c\u8138\u5c0f\u6484","WallPaperMiddle":"http:\/\/bzpic.spriteapp.cn\/250x445\/picture2\/M00\/0A\/34\/wKiFWVOnjOKAG256AAF-TNkxjfk670.jpg","WallPaperBig":"http:\/\/bzpic.spriteapp.cn\/1080x1920\/picture2\/M00\/0A\/34\/wKiFWVOnjOKAG256AAF-TNkxjfk670.jpg","WallPaperDownloadPath":"http:\/\/bzpic.spriteapp.cn\/1080x1920\/picture2\/M00\/0A\/34\/wKiFWVOnjOKAG256AAF-TNkxjfk670.jpg","WallPaperSource":"http:\/\/bzpic.spriteapp.cn\/744x1392\/picture2\/M00\/0A\/34\/wKiFWVOnjOKAG256AAF-TNkxjfk670.jpg","weixin_url":"http:\/\/www.budejie.com\/bz\/bdj-10983477.html?wx.qq.com"},{"ID":10984404,"PicName":"10984404.jpg","pic_path":"\/picture2\/M00\/0A\/63\/wKiFWVOzZ2mAbBJMAAOejEuFIXI097.jpg","BigCategoryId":1040,"SecondCategoryId":2624,"CreateTime":"2014-07-02
09:57:01","passtime":"2016-06-05 11:41:49","UserName":"73706","DownloadCount":10111,"GoodCount":10128,"tags":"\u674e\u51b0\u51b0 \u7f8e\u5973","WallPaperMiddle":"http:\/\/bzpic.spriteapp.cn\/250x445\/picture2\/M00\/0A\/63\/wKiFWVOzZ2mAbBJMAAOejEuFIXI097.jpg","WallPaperBi

这是返回的json,太长了,你发现其实json返回还不完整.但是请求是成功的,知道了get异步请求带参数就行

Post请求

OkHttpClient client = new OkHttpClient();
RequestBody formBody = new FormBody.Builder()
.add("name", "zgz")
.add("time",""+System.currentTimeMillis())
.add("id","1")
.build();
Request request = new Request.Builder().url("http://zhushou.72g.com/app/gift/gift_list/").post(formBody).build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e(TAG,"请求失败="+e);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if(null!=response&&response.isSuccessful()){
Log.e(TAG,"content="+response.body().string());
}
}
});

请求结果log:

11-24 00:48:16.787 18590-18714/com.simple E/MainActivity: content={"info":[],"page":{"total":0,"pagesize":10,"page":1,"page_total":0},"state":"success"}

ok,post请求也是成功的,

文件下载

以从豆瓣网下载一个图片为例,

public void download(View view){
OkHttpClient client = new OkHttpClient();
String url = "https://img3.doubanio.com/view/photo/m/public/p2304620571.webp";
Request request = new Request.Builder().url(url).build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e(TAG,"下载失败="+e);
}
@Override
public void onResponse(Call call, Response response) {
if(null!=response&&response.isSuccessful()){
Log.e(TAG,"下载成功=");
InputStream inputStream = response.body().byteStream();
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(new File(getPath(),"/zgz1.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) {
Log.e(TAG,"下载过程中失败="+e);
}finally {
try {
if(null!=fileOutputStream){
fileOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(inputStream!=null){
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}

}
}
}
});
}

这是get方式文件下载.

文件上传

这个需要自己搭建服务器了,昨晚在eclipse弄了好久,就是跑不起来,今天下载了一个myeclipse,再弄弄,把刚才下载的图片上传.又弄了好久终于把这文件上传弄好了

服务端代码:

package com.simple.upload;

import java.io.IOException;

import java.io.PrintWriter;

import javax.servlet.ServletException;

import javax.servlet.annotation.MultipartConfig;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.Part;

@MultipartConfig

@WebServlet("/UploadServlet")

public class UploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

    public UploadServlet() {

        super();

    }
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
String name=request.getParameter("name");
System.out.println("name="+name);
Part part=request.getPart("fileimage");
PrintWriter out=response.getWriter();
out.print("name="+name+"\n");
System.out.println("ContentType="+part.getContentType()+"\n");
out.print("ContentType="+part.getContentType()+"\n");
System.out.println("size="+part.getSize()+"\n");
out.print("size="+part.getSize()+"\n");
part.write("C://Users/zhouguizhijxhz/zgz.jpg");
}

}

客户端上传文件的代码:

public void file_upload(View view){
new Thread(){
@Override
public void run() {
File file = new File(getPath(),"/zgz2.jpg");
RequestBody imageBody = RequestBody.create(MediaType.parse("image/jpeg"), file);
MultipartBody body = new MultipartBody.Builder().
setType(MultipartBody.FORM).//这是你再上传文件的同时还要传递参数就必须写这个setType()
addFormDataPart("name", "zhouguizhi").
addFormDataPart("fileimage", "zgz.jpg", imageBody).build();
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().
url("http://192.168.1.107:8080/aa/UploadServlet").post(body).build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e(TAG,"上传文件失败原因="+e);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.e(TAG,"上传文件onResponse=");
if (response.isSuccessful()) {
Log.e(TAG,"上传文件="+response.code());
}
}
});
}
}.start();
}


public String getPath(){
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
return path;
}


看下myeclipse的控制台:



上传的文件我是存储在

part.write("C://Users/zhouguizhijxhz/zgz.jpg");

这个目录下:



这个文件上传,我是又下载了eclipse 不行今天又下载了myEclipse 不容易啊。

最后讲一下okhttp的缓存了,前提是你服务器端要支持缓存,如果不支持缓存的话,设置也是没毛用的.哦,还有一个设置超时的问题,这个简单,先说下,设置超时这些操作肯定是在一个全局中,就好比我们不可能每个请求都是去设置超时,所以不可能在Request类中,而是在OkhttpClient类

设置超时



看看下面这些方法,又是采用了builder模式,okhttp3框架中大量的使用了builder模式,如果不设置的话,默认是10秒.

connectTimeout = 10_000;
readTimeout = 10_000;
writeTimeout = 10_000;
pingInterval = 0;

这是它源码中的默认值,在这也简单的设置下:
OkHttpClient okHttpClient = new OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10,TimeUnit.SECONDS)
.build();


缓存设置

public void cache(View view){
new Thread(){
@Override
public void run() {
int maxCacheSize = 10 * 1024 * 1024;
//缓存在sd卡中
Cache cache = new Cache(createMdkir(), maxCacheSize);
OkHttpClient client = new OkHttpClient.Builder().cache(cache).build();
Request request = new Request.Builder().url("http://www.qq.com/").
cacheControl(new CacheControl.Builder().maxStale(1, TimeUnit.DAYS).build()).
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 {
Log.e(TAG,"json="+response.body().string());
}
});
}
}.start();
}

如果成功了后会在你缓存的目录下有三个文件

接下来会整合一个简单好使用的工具类.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: