android okhttp3框架使用

今天总结下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();
}
如果成功了后会在你缓存的目录下有三个文件

接下来会整合一个简单好使用的工具类.



猜你喜欢

转载自blog.csdn.net/coderinchina/article/details/78616979