OkHttp+Retrofit+RajavaAndroid 开发Android第三方类库

OkHttp缓存配置

2016-06-04  本文已影响2562人  TrancyDeng

前言

废话不多说,先奉上
OkHttp GitHub

说到OKHTTP,我想你肯定不会陌生,Android中无数大大小小的项目在用这个开源库,甚至包括Google开发的一些项目也在用。Android API23 抛弃了httpclient之后,我想肯定会有很多人在为寻找下一个好用的网络库而犯愁。看到这里,我认为你走对了。

OkHttp使用的几种方式

OkHttp的性能我自不必说,关于使用方式(异步GET,同步GET...)自不必说,网上资料非常多。在这里我直接贴出代码。

同步get

下载一个文件,打印他的响应头,以string形式打印响应体。
  响应体的 string() 方法对于小文档来说十分方便、高效。但是如果响应体太大(超过1MB),应避免适应 string()方法 ,因为他会将把整个文档加载到内存中。对于超过1MB的响应body,应使用流的方式来处理body。

private final OkHttpClient client = new OkHttpClient();

public void run() throws Exception {
    Request request = new Request.Builder()
        .url("http://publicobject.com/helloworld.txt")
        .build();

    Response response = client.newCall(request).execute();
    if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

    Headers responseHeaders = response.headers();
    for (int i = 0; i < responseHeaders.size(); i++) {
      System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
    }

    System.out.println(response.body().string());
}

异步get

在一个工作线程中下载文件,当响应可读时回调Callback接口。读取响应时会阻塞当前线程。OkHttp现阶段不提供异步api来接收响应体。

private final OkHttpClient client = new OkHttpClient();

public void run() throws Exception {
    Request request = new Request.Builder()
        .url("http://publicobject.com/helloworld.txt")
        .build();

    client.newCall(request).enqueue(new Callback() {
      @Override public void onFailure(Request request, Throwable throwable) {
        throwable.printStackTrace();
      }

      @Override public void onResponse(Response response) throws IOException {
        if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

        Headers responseHeaders = response.headers();
        for (int i = 0; i < responseHeaders.size(); i++) {
          System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
        }

        System.out.println(response.body().string());
      }
    });
}

Post方式提交String

使用HTTP POST提交请求到服务。这个例子提交了一个markdown文档到web服务,以HTML方式渲染markdown。因为整个请求体都在内存中,因此避免使用此api提交大文档(大于1MB)。

public static final MediaType MEDIA_TYPE_MARKDOWN
  = MediaType.parse("text/x-markdown; charset=utf-8");

private final OkHttpClient client = new OkHttpClient();

public void run() throws Exception {
    String postBody = ""
        + "Releases\n"
        + "--------\n"
        + "\n"
        + " * _1.0_ May 6, 2013\n"
        + " * _1.1_ June 15, 2013\n"
        + " * _1.2_ August 11, 2013\n";

    Request request = new Request.Builder()
        .url("https://api.github.com/markdown/raw")
        .post(RequestBody.create(MEDIA_TYPE_MARKDOWN, postBody))
        .build();

    Response response = client.newCall(request).execute();
    if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

    System.out.println(response.body().string());
}

Post方式提交文件

直接封装好文件体就可以

public static final MediaType MEDIA_TYPE_MARKDOWN
  = MediaType.parse("text/x-markdown; charset=utf-8");

private final OkHttpClient client = new OkHttpClient();

public void run() throws Exception {
    File file = new File("README.md");

    Request request = new Request.Builder()
        .url("https://api.github.com/markdown/raw")
        .post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file))
        .build();

    Response response = client.newCall(request).execute();
    if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

    System.out.println(response.body().string());
}

Post方式提交表单

估计这是一种最常用的方式了

private final OkHttpClient client = new OkHttpClient();

public void run() throws Exception {
    RequestBody formBody = new FormEncodingBuilder()
        .add("search", "Jurassic Park")
        .build();
    Request request = new Request.Builder()
        .url("https://en.wikipedia.org/w/index.php")
        .post(formBody)
        .build();

    Response response = client.newCall(request).execute();
    if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

    System.out.println(response.body().string());
}

缓存策略

我当初在这方面卡了一些时间。这也是今天的重点。

<code>
File httpCacheDirectory = new File(pActivity.getExternalCacheDir(), "cache_zhiyixing");
</code>

首先创建文件缓存目录,这里有两个参数

new OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .cache(new Cache(httpCacheDirectory, 1024 * 1024 * 10)).build();

通过OKHTTP的构建者模式把文件目录传入进去。运行之后,从外置存储中你会发现缓存目录已经创建完成。而且内容也已经缓存进去了。

断网,再次打开软件,发现并不能把缓存读取出来。
这是为什么呢?
  这是OKHTTP的缓存策略导致的。用户可以设置cache-control来控制缓存的时效。有关cache-control的介绍请戳这里,不能翻墙的戳这里

这里我把配置代码放上

package com.android.zhixing.model;

import android.content.Context;

import com.android.zhixing.utils.NetWorkUtils;
import com.socks.library.KLog;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * Created by dengqiangxi on 16/5/30.
 */
public class OurOkHttpClient {

    public static OkHttpClient getClient(final Context pActivity) {
        File httpCacheDirectory = new File(pActivity.getExternalCacheDir(), "cache_zhiyixing");

        return new OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .cache(new Cache(httpCacheDirectory, 1024 * 1024 * 10))
                .addInterceptor(new Interceptor() {
                    @Override
                    public Response intercept(Chain chain) throws IOException {
                        Request request = chain.request();
                        Log.e("新请求", "=request==" + request.toString());
                        Response response = chain.proceed(request);
                        if (NetWorkUtils.isNetworkReachable(pActivity)) {
                            int maxAge = 60 * 60*24; // 有网络的时候从缓存1天后失效
                            response.newBuilder()
                                    .removeHeader("Pragma")
                                .header("Cache-Control", "public, max-age=" + maxAge)
                                     .build();
                        } else {
                            int maxStale = 60 * 60 * 24 * 28; // // 无网络缓存保存四周
                            response.newBuilder()
                                    .removeHeader("Pragma")
                                    .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                                    .build();
                        }
                        return response;
                    }
                })
                .build();

    }
}

至此,有关OKHTTP的相关配置就已经介绍完了,下一节将介绍OKHTTP和retrofit结合使用。

上一篇下一篇

猜你喜欢

热点阅读