Android 无法从缓存加载数据okHttp&;改造

Android 无法从缓存加载数据okHttp&;改造,android,caching,retrofit,retrofit2,okhttp3,Android,Caching,Retrofit,Retrofit2,Okhttp3,以下是我调用api的代码,并通过改装为okhttp定义缓存: public class DemoPresenter { DemoView vDemoView; private Context mContext; public DemoPresenter(Context mcontext, DemoView vDemoView) { this.vDemoView = vDemoView; this.mContext = mcontext;

以下是我调用api的代码,并通过改装为okhttp定义缓存:

public class DemoPresenter {

    DemoView vDemoView;
    private Context mContext;

    public DemoPresenter(Context mcontext, DemoView vDemoView) {
        this.vDemoView = vDemoView;
        this.mContext = mcontext;
    }

    public void callAllProduct() {
        if (vDemoView != null) {
            vDemoView.showProductProgressBar();
        }


        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .cache(new Cache(mContext.getCacheDir(), 10 * 1024 * 1024)) // 10 MB
                .addInterceptor(new Interceptor() {
                    @Override
                    public okhttp3.Response intercept(Chain chain) throws IOException {
                        Request request = chain.request();
                        if (BasicUtility.isInternet(mContext)) {
                            request = request.newBuilder().header("Cache-Control", "public, max-age=" + 60).build();
                        } else {
                            request = request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + 60 * 60 * 24 * 7).build();
                        }
                        return chain.proceed(request);
                    }
                })
                .build();


        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("www.xyz.com/data/")
                .addConverterFactory(GsonConverterFactory.create())
                .client(okHttpClient)
                .build();

        AllApi productApiService = retrofit.create(AllApi.class);
        Call<ProductData> call = productApiService.getProduct();

        try {
            call.enqueue(new Callback<ProductData>() {
                @Override
                public void onResponse(Call<ProductData> call, Response<ProductData> response) {
                    ArrayList<Product> alproducts = new ArrayList<>();
                    try {
                        alproducts = response.body().getProductData();
                        onSuccess(alproducts);
                    } catch (Exception e) {

                    }
                }
                @Override
                public void onFailure(Call<ProductData> call, Throwable t) {
                }
            });
        } catch (Exception e) {

        }
    }

    private void onSuccess(ArrayList<Product> alproducts) {
        if (vDemoView != null) {
            vDemoView.hideProductProgressBar();
            vDemoView.onProductSuccess(alproducts);
        }
    }
}
现在,当我使用Internet连接运行此活动时,它工作正常,但当我断开Internet并再次运行此活动时,它将不会从缓存加载数据

如果没有internet,如何从缓存加载此数据?

您可以尝试以下方法:

public class DemoPresenter {

    DemoView vDemoView;
    private Context mContext;
    private static final String CACHE_CONTROL = "Cache-Control";
    private static final String TAG = DemoPresenter.class.getName();

    public DemoPresenter(Context mcontext, DemoView vDemoView) {
        this.vDemoView = vDemoView;
        this.mContext = mcontext;
    }

    public void callAllProduct() {
        if (vDemoView != null) {
            vDemoView.showProductProgressBar();
        }


        OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .addInterceptor( provideOfflineCacheInterceptor() )
            .addNetworkInterceptor( provideCacheInterceptor() )
            .cache( provideCache() )
            .build();


       /* OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .cache(new Cache(mContext.getCacheDir(), 10 * 1024 * 1024)) // 10 MB
                .addInterceptor(new Interceptor() {
                    @Override
                    public okhttp3.Response intercept(Chain chain) throws IOException {
                        Request request = chain.request();
                        if (BasicUtility.isInternet(mContext)) {
                            request = request.newBuilder().header("Cache-Control", "public, max-age=" + 60).build();
                        } else {
                            request = request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + 60 * 60 * 24 * 7).build();
                        }
                        return chain.proceed(request);
                    }
                })
                .build();*/


        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("www.xyz.com/data/")
                .addConverterFactory(GsonConverterFactory.create())
                .client(okHttpClient)
                .build();

        AllApi productApiService = retrofit.create(AllApi.class);
        Call<ProductData> call = productApiService.getProduct();

        try {
            call.enqueue(new Callback<ProductData>() {
                @Override
                public void onResponse(Call<ProductData> call, Response<ProductData> response) {
                    ArrayList<Product> alproducts = new ArrayList<>();
                    try {
                        alproducts = response.body().getProductData();
                        onSuccess(alproducts);
                    } catch (Exception e) {

                    }
                }
                @Override
                public void onFailure(Call<ProductData> call, Throwable t) {
                }
            });
        } catch (Exception e) {

        }
    }

    private void onSuccess(ArrayList<Product> alproducts) {
        if (vDemoView != null) {
            vDemoView.hideProductProgressBar();
            vDemoView.onProductSuccess(alproducts);
        }
    }

    public Interceptor provideOfflineCacheInterceptor () {
        return new Interceptor()
        {
            @Override
            public Response intercept (Chain chain) throws IOException
            {
                Request request = chain.request();

                if (BasicUtility.isInternet(mContext))
                {
                    CacheControl cacheControl = new CacheControl.Builder()
                        .maxStale( 7, TimeUnit.DAYS )
                        .build();

                    request = request.newBuilder()
                        .cacheControl( cacheControl )
                        .build();
                }

                return chain.proceed( request );
            }
        };
    }




    public static Interceptor provideCacheInterceptor ()
    {
        return new Interceptor()
        {
            @Override
            public Response intercept (Chain chain) throws IOException
            {
                Response response = chain.proceed( chain.request() );

                // re-write response header to force use of cache
                CacheControl cacheControl = new CacheControl.Builder()
                    .maxAge( 1, TimeUnit.MINUTES )
                    .build();

                return response.newBuilder()
                    .header( CACHE_CONTROL, cacheControl.toString() )
                    .build();
            }
        };
    }

    private Cache provideCache ()
    {
        Cache cache = null;
        try
        {
            cache = new Cache( new File( mContext.getCacheDir(), "http-cache" ),
                10 * 1024 * 1024 ); // 10 MB
        }
        catch (Exception e)
        {
            Log.e(TAG, "Could not create Cache!");
        }
        return cache;
    }
}
公共类演示者{
DemoView-vDemoView;
私有上下文;
私有静态最终字符串CACHE\u CONTROL=“CACHE CONTROL”;
私有静态最终字符串标记=DemoPresenter.class.getName();
公共演示者(上下文mcontext、演示视图vDemoView){
this.vDemoView=vDemoView;
this.mContext=mContext;
}
public void callAllProduct(){
如果(vDemoView!=null){
vDemoView.showProductProgressBar();
}
OkHttpClient OkHttpClient=新建OkHttpClient.Builder()
.addInterceptor(provideOfflineCacheInterceptor())
.addNetworkInterceptor(provideCacheInterceptor())
.cache(provideCache())
.build();
/*OkHttpClient OkHttpClient=新建OkHttpClient.Builder()
.cache(新缓存(mContext.getCacheDir(),10*1024*1024))//10 MB
.addInterceptor(新拦截器(){
@凌驾
公共okhttp3.响应截获(链)引发IOException{
Request=chain.Request();
if(BasicUtility.isInternet(mContext)){
request=request.newBuilder().header(“缓存控制”,“公共,最大年龄=“+60”).build();
}否则{
request=request.newBuilder().header(“缓存控制”,“公共,仅当缓存时,max stale=“+60*60*24*7”).build();
}
返回链。继续(请求);
}
})
.build()*/
改装改装=新改装.Builder()
.baseUrl(“www.xyz.com/data/”)
.addConverterFactory(GsonConverterFactory.create())
.客户(okHttpClient)
.build();
AllApi productApiService=reformation.create(AllApi.class);
Call Call=productApiService.getProduct();
试一试{
call.enqueue(新回调(){
@凌驾
公共void onResponse(调用、响应){
ArrayList alproducts=新的ArrayList();
试一试{
alproducts=response.body().getProductData();
成功(alproducts);
}捕获(例外e){
}
}
@凌驾
失败时公共无效(调用调用,可丢弃的t){
}
});
}捕获(例外e){
}
}
私有void onSuccess(ArrayList alproducts){
如果(vDemoView!=null){
vDemoView.hideProductProgressBar();
vDemoView.onProductSuccess(alproducts);
}
}
公共侦听器提供OfflineCacheInterceptor(){
返回新的拦截器()
{
@凌驾
公共响应拦截(链)引发IOException
{
Request=chain.Request();
if(BasicUtility.isInternet(mContext))
{
CacheControl CacheControl=新建CacheControl.Builder()
.maxStale(7,TimeUnit.DAYS)
.build();
request=request.newBuilder()
.cacheControl(cacheControl)
.build();
}
返回链。继续(请求);
}
};
}
公共静态拦截器provideCacheInterceptor()
{
返回新的拦截器()
{
@凌驾
公共响应拦截(链)引发IOException
{
响应=chain.procedure(chain.request());
//重新写入响应头以强制使用缓存
CacheControl CacheControl=新建CacheControl.Builder()
.maxAge(1,TimeUnit.MINUTES)
.build();
返回响应。newBuilder()
.header(CACHE\u控件,cacheControl.toString())
.build();
}
};
}
专用缓存提供缓存()
{
Cache=null;
尝试
{
cache=新缓存(新文件(mContext.getCacheDir(),“http缓存”),
10*1024*1024);//10 MB
}
捕获(例外e)
{
Log.e(标记“无法创建缓存!”);
}
返回缓存;
}
}

对我来说工作得很好。

您的拦截器应该检查连接,并相应地设置cacheHeaderValue,在本例中,它使用isNetworkAvailable方法来执行此操作:

okClient.interceptors().add(
                new Interceptor() {
                    @Override
                    public Response intercept(Chain chain) throws IOException {
                        Request originalRequest = chain.request();
                        String cacheHeaderValue = isNetworkAvailable(context)
                                ? "public, max-age=2419200"
                                : "public, only-if-cached, max-stale=2419200" ;
                        Request request = originalRequest.newBuilder().build();
                        Response response = chain.proceed(request);
                        return response.newBuilder()
                                .removeHeader("Pragma")
                                .removeHeader("Cache-Control")
                                .header("Cache-Control", cacheHeaderValue)
                                .build();
                    }
                }
        );
        okClient.networkInterceptors().add(
                new Interceptor() {
                    @Override
                    public Response intercept(Chain chain) throws IOException {
                        Request originalRequest = chain.request();
                        String cacheHeaderValue = isNetworkAvailable(context)
                                ? "public, max-age=2419200"
                                : "public, only-if-cached, max-stale=2419200" ;
                        Request request = originalRequest.newBuilder().build();
                        Response response = chain.proceed(request);
                        return response.newBuilder()
                                .removeHeader("Pragma")
                                .removeHeader("Cache-Control")
                                .header("Cache-Control", cacheHeaderValue)
                                .build();
                    }
                }
        );

您需要为OkHttp添加脱机缓存拦截器,以缓存响应以供脱机使用。您还可以将数据缓存一分钟,如果请求在一分钟内发送,则使用缓存中的数据

/**
 * Interceptor to cache data and maintain it for four weeks.
 *
 * If the device is offline, stale (at most four weeks old)
 * response is fetched from the cache.
 */
private static class OfflineResponseCacheInterceptor implements Interceptor {
    @Override
    public okhttp3.Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        if (!UtilityMethods.isNetworkAvailable()) {
            request = request.newBuilder()
                    .header("Cache-Control",
                      "public, only-if-cached, max-stale=" + 2419200)
                    .build();
        }
        return chain.proceed(request);
    }
}
按照本教程了解有关缓存数据的更多信息- 这也是堆栈溢出的答案
可能的错误:因为您将所有内容都放在
callAllProduct
()中,所以每次创建新的
okHttpClient
,以及新的
缓存时,您都不会重用旧的
缓存。您在功能上依赖于callAllProduct,callAllProduct依赖于新的okHttpClient,okHttpCient的功能依赖于新的缓存。将
okHttpClient
置于
callAllProduct
()主体之外会使您依赖于相同的旧okHttpClien
/**
 * Interceptor to cache data and maintain it for four weeks.
 *
 * If the device is offline, stale (at most four weeks old)
 * response is fetched from the cache.
 */
private static class OfflineResponseCacheInterceptor implements Interceptor {
    @Override
    public okhttp3.Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        if (!UtilityMethods.isNetworkAvailable()) {
            request = request.newBuilder()
                    .header("Cache-Control",
                      "public, only-if-cached, max-stale=" + 2419200)
                    .build();
        }
        return chain.proceed(request);
    }
}
 int cacheSize = 10 * 1024 * 1024; /* 10 MB. Also try increasing cache size */
    public static Cache myCache = new Cache(getCacheDir(), cacheSize);

  OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .cache(myCache) // 10 MB
                .addInterceptor(new Interceptor() {
                    @Override
                    public okhttp3.Response intercept(Chain chain) throws IOException {
                        Request request = chain.request();
                        if (BasicUtility.isInternet(mContext)) {
                            request = request.newBuilder().header("Cache-Control", "public, max-age=" + 60).build();
                        } else {
                            request = request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + 60 * 60 * 24 * 7).build();
                        }
                        return chain.proceed(request);
                    }
                })
                .build();
public void callAllProduct() {
        if (vDemoView != null) {
            vDemoView.showProductProgressBar();
        }

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("www.xyz.com/data/")
                .addConverterFactory(GsonConverterFactory.create())
                .client(okHttpClient)
                .build();

        AllApi productApiService = retrofit.create(AllApi.class);
        Call<ProductData> call = productApiService.getProduct();

        try {
            call.enqueue(new Callback<ProductData>() {
                @Override
                public void onResponse(Call<ProductData> call, Response<ProductData> response) {
                    ArrayList<Product> alproducts = new ArrayList<>();
                    try {
                        alproducts = response.body().getProductData();
                        onSuccess(alproducts);
                    } catch (Exception e) {

                    }
                }
                @Override
                public void onFailure(Call<ProductData> call, Throwable t) {
                }
            });
        } catch (Exception e) {

        }
    }