Android网络缓存,retrofit+okhttp

本文是我对自己掌握的网络缓存知识做一个总结,希望能对大家有所帮助,如有侵权,我改改就好了0.0

缓存过程

  • 客户端-缓存-网络-拦截器

Android网络缓存,retrofit+okhttp_第1张图片

CacheControl类

  1. noCache 不使用缓存,全部走网络
  2. noStore 不使用缓存,也不存储缓存
  3. onlyIfCached 只使用缓存
  4. maxAge 设置最大失效时间,失效则不使用
  5. maxStale 设置最大失效时间,失效则不使用
  6. minFresh 设置有效时间
  7. FORCE_NETWORK 只走网络
  8. FORCE_CACHE 只走缓存

标识为 no-cache 的响应实际上是可以存储在本地缓存区中的。 只是在与原始服务器进行再验证之前,缓存不能将其提供给客户端使用,并不是不缓存的意思


依赖包

    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'
    compile 'com.squareup.okhttp3:okhttp:3.3.1'
    compile 'com.squareup.okhttp3:logging-interceptor:3.3.1'
    compile 'com.zhy:okhttputils:2.6.2'

示例代码

public class RetrofitManager {
    private static OkHttpClient mOkHttpClient;
    private static final String TAG = "OkHttp";

    //短缓存1分钟
    public static final int CACHE_AGE_SHORT = 60;
    //长缓存有效期为1天
    public static final int CACHE_STALE_LONG = 60 * 60 * 24;
    //自己的base_url
    public static final String BASE_URL = "http://www.baidu.com";

    private ApiServer apiServer;
    private static RetrofitManager instance = new RetrofitManager();

    public static RetrofitManager getInstance() {
        return instance;
    }

    private RetrofitManager() {
        initOkHttpClient();
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .client(mOkHttpClient)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        apiServer = retrofit.create(ApiServer.class);
    }

    private void initOkHttpClient() {
        //日志拦截,使用okhttputils的HttpLoggingInterceptor,设置请求级别
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
            @Override
            public void log(String message) {
                Log.e(TAG, message);
            }
        });
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        //缓存的cookieJar负责管理cookies
        com.zhy.http.okhttp.cookie.CookieJarImpl cookieJar = new com.zhy.http.okhttp.cookie.CookieJarImpl(new PersistentCookieStore(App.getInstance()));
        //单例
        if (mOkHttpClient == null) {
            synchronized (OkHttpClient.class) {
                if (mOkHttpClient == null) {
                    // 指定缓存路径,缓存大小10Mb
                    Cache cache = new Cache(new File(App.getInstance().getCacheDir(), "HttpCache"),
                            1024 * 1024 * 10);
                    mOkHttpClient = new OkHttpClient.Builder()
                            .cache(cache)
                            .addInterceptor(interceptor)
                            .addNetworkInterceptor(mCacheControlInterceptor)
                            .cookieJar(cookieJar)
                            .retryOnConnectionFailure(true)
                            .connectTimeout(60, TimeUnit.SECONDS)
                            .readTimeout(60, TimeUnit.SECONDS)
                            .writeTimeout(60, TimeUnit.SECONDS)
                            .build();
                }
            }
        }
    }

    public static ApiServer build() {
        return instance.apiServer;
    }

    // 响应头拦截器,用来配置缓存策略
    private Interceptor mCacheControlInterceptor = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            if (!NetUtils.isConnected(App.getInstance())) {
                //没网时只使用缓存
                //自定义请求头,可以在响应头对请求头的header进行拦截,配置不同的缓存策略
                request = request.newBuilder()
                        .header("head-request", request.toString())
                        .cacheControl(CacheControl.FORCE_CACHE)
                        .build();
            }
            Response response = chain.proceed(request);
            if (NetUtils.isConnected(App.getInstance())) {
                //有网的时候读接口上的@Headers里的配置,你可以在这里进行统一的设置
                Log.e("Interceptor", "response: " + response.toString());
                //添加头信息,配置Cache-Control
                //removeHeader("Pragma") 使缓存生效
                return response.newBuilder()
                        .header("Cache-Control", "public, max-age=" + CACHE_AGE_SHORT)
                        .removeHeader("Pragma")
                        .build();
            } else {
                Log.e("Interceptor", "net not connect");
                return response.newBuilder()
                        .header("Cache-Control", "public,only-if-cached, max-stale=" + CACHE_STALE_LONG)
                        .removeHeader("Pragma")
                        .build();
            }
        }
    };

}

总结

缓存设置了也不一定生效,因为设置缓存保存下来是一个异步的过程,可能你请求网络保存缓存还没成功就进行了第二次请求,这样缓存就没生效了,一般只有get请求可以设置缓存,post请求无法被缓存,一般的显示列表信息或者不需要频繁刷新的页面可以设置get请求以及缓存,不然也不是很必要,根据缓存策略就好,比如希望用户离线还可以查看一定的页面信息。

你可能感兴趣的:(Android开发)