okhttp的详解及其缓存的使用

来源:互联网 发布:haproxy和nginx的区别 编辑:程序博客网 时间:2024/05/03 06:06

一、概述
随着Okhttp使用越来越普遍,他的方便之处也被人熟知,本章简单介绍一下okhttp的使用过程:

  • get请求
  • Post请求
  • 文件的上传和下载
  • okhttp缓存的使用
  • 平时使用可参照鸿洋大神封装的okhttpUtils点击前往
    使用前准备:
    Android Studio用户可以添加以下依赖:
compile 'com.squareup.okhttp:okhttp:2.4.0'

二、使用过程
- get请求:

OkHttpClient okHttpClient = new OkHttpClient();        Request request = new Request.Builder().url("htttp://baidu.com").build();        Call call = okHttpClient.newCall(request);        call.enqueue(new Callback() {            @Override            public void onFailure(Call call, IOException e) {            }            @Override            public void onResponse(Call call, Response response) throws IOException {                //TODO            }        });

根据上面代码看出okhttp的get请求一般步骤:
- 创建okhttpClient 对象
- 构建请求的Request(url()传入请求接口、build生成Request对象)
- 利用Request对象构建Call对象
- call.enqueue()加入调度队列,这里使用异步请求,另有excute()和cancel()。
- 在回调Callback中得到Response后,就可以根据需求获取返回结果如:response.body().string() 获取字符串; response.body().byteStream() 获取输入流; response.body().bytes()获取字节数组;
如果不采用异步请求上述代码可写成:

Request request = new Request.Builder().url("htttp://baidu.com").build();        try {            Response response = (new OkHttpClient().newCall(request)).execute();        } catch (IOException e) {            e.printStackTrace();        }
  • Post请求(携带参数请求)
 OkHttpClient okHttpClient = new OkHttpClient();        FormBody formBody = new FormBody.Builder().add("KEY","Value").build();        Request request = new Request.Builder().url("htttp://baidu.com").post(formBody).build();        Call call = okHttpClient.newCall(request);        call.enqueue(new Callback() {            @Override            public void onFailure(Call call, IOException e) {            }            @Override            public void onResponse(Call call, Response response) throws IOException {            }        });

与get请求相比,Post的使用大致相同,只是request的构造形式不同,先构造Formbody传入要携带的参数用来构造RequestBody,利用Post()提交请求。
3. 文件的上传和下载
单个文件的上传

 File file ;        if (!Environment.isExternalStorageRemovable() || Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()))            file = new File(getApplication().getExternalCacheDir(),"test.text");        else            file = new File (getApplication().getCacheDir(),"test.text");        RequestBody requestBody = RequestBody.create(MediaType.parse("text/x-markdown; charset=utf-8"),file);        OkHttpClient okHttpClient = new OkHttpClient();        Request request = new Request.Builder().url("htttp://baidu.com").post(requestBody).build();        Call call = okHttpClient.newCall(request);        call.enqueue(new Callback() {            @Override            public void onFailure(Call call, IOException e) {            }            @Override            public void onResponse(Call call, Response response) throws IOException {            }        });    }

Post分块上传,同时上传键值对和文件RequestBody构造如下:

RequestBody requestBody_all =  new MultipartBody.Builder().setType(MultipartBody.FORM).addPart(Headers.of("Content-Disposition",                "form-data; name=\"username\""),RequestBody.create(null,"Alex")).addPart(Headers.of("Content-Disposition","form-data;name=\"filename\""),requestBody).build();        OkHttpClient okHttpClient = new OkHttpClient();        Request request = new Request.Builder().url("htttp://baidu.com").post(requestBody_all).build();

请求之间的区别主要在于RequestBody之间的区别
文件的下载:
利用请求得到的response.body().byteStream() 得到输入流后,进行写入即可

三、 缓存
在App使用过程中,若信息没有任何改变而用户多次请求时,会造成流量的浪费和无意义的请求,尤其在一些数据不是经常变化的地方,使用缓存可以很好的提高用户体验和节省流量
1. 缓存策略
HTTP1.0使用的Expires过期策略,使用时间戳来判断是否过期,但是当客户端的时间和服务端时间不一致时会造成判断失误,HTTP1.1以上都采用Cache-control策略,此策略使用时间长度判断是否过期,即只根据两次请求之间的时间差判断是否有效,避免之前的问题,基本格式:

Cache-Control:max-age+ 3600 * 24 * 30
  1. 缓存的原理
    okhttp的缓存是通过拦截器intercept来实现的,添加拦截器:
new OkHttpClient.Builder().addInterceptor(new MyInterceptor);

okhttp内部定义一个ListInterceptor将每个添加的Interceptor 添加集合当中,最后遍历每个拦截器将每个请求体封装成Chain交给每个拦截器处理,在拦截器中修改请求头,使用Cache-control策略:

Response response1 = response.newBuilder()                .removeHeader("Pragma")                .removeHeader("Cache-Control")                .header("Cache-Control", "max-age=" + 3600 * 24 * 30)                .build();
  1. 缓存的使用
    服务器端支持缓存:
    若服务器端支持缓存,请求返回的Response的头文件会带有Header:Cache-Control, max-age=xxx,此时只需要设置缓存的文件,一般采用Android推荐使用Context.getCacheDir()来作为缓存的存放路径,另外还需要指定缓存的大小就可以创建一个缓存了,okhttp会自动帮你缓存了:
OkHttpClient okHttpClient = new OkHttpClient.Builder().cache(getCache())                .connectTimeout(20, TimeUnit.SECONDS)                .readTimeout(20,TimeUnit.SECONDS)                .writeTimeout(20,TimeUnit.SECONDS)                .build();public Cache getCache(){        return new Cache(mContext.getCacheDir(),1024*1024*10);    }

服务器端不支持缓存
此时需要创建Interceptor对象,修改请求返回的Response:

public class  MyInterceptor implements Interceptor{        @Override        public Response intercept(Chain chain) throws IOException {            Request request = chain.request();            Response response = chain.proceed(request);            Response response1 = response.newBuilder().removeHeader("Pragma").removeHeader("Cache-Control")                    .header("Cache-Control", "max-age=" + 3600 * 24 * 30).build();            return response1;        }    }

参考文章

  • 泡网okhttp使用教程
  • Okhttp缓存解析
1 0