简体   繁体   English

离线缓存okhttp + retrofit无法正常工作

[英]Offline cache okhttp + retrofit not working

I am trying to activate a cache for offline browsing when no network is available. 我正在尝试在没有网络可用时激活缓存以进行离线浏览。 Unfortunatly it is somehow not working, when I debug the app, the interceptor nor cache is being accessed. 不幸的是,它在某种程度上不起作用,当我调试应用程序时,正在访问拦截器和缓存。

So I guess something is wrong with below code. 所以我想下面的代码有问题。

public class ApiHelper {

    Context context;
    private static final int TIMEOUT = 30;
    private static final int WRITE_TIMEOUT = 30;
    private static final int CONNECT_TIMEOUT = 10;
    //private static final int CACHE_SIZE = 500 * 1024 * 1024;
    private static final int CACHE_SIZE = 10 * 1024 * 1024;

    public static final String baseUrl = "http://test.com/api-new/";

    public ApiHelper(Context context) {
        this.context = context;
    }

    private boolean isNetworkAvailable(Context context) {
        ConnectivityManager connectivityManager
                = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        return activeNetworkInfo != null && activeNetworkInfo.isConnected();
    }


    // Configure access cache when offline
    private final Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Response originalResponse = chain.proceed(chain.request());
            if (isNetworkAvailable(context)) {
                int maxAge = 60; // read from cache for 1 minute
                return originalResponse.newBuilder()
                        .removeHeader("Pragma")
                        .header("Cache-Control", "public, max-age=" + maxAge)
                        .build();
            } else {
                int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale
                return originalResponse.newBuilder()
                        .removeHeader("Pragma")
                        .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                        .build();
            }
        }
    };


    private static OkHttpClient CLIENT = new OkHttpClient();

    File httpCacheDirectory = new File(context.getCacheDir(), "HttpCache");
    Cache cache = new Cache(httpCacheDirectory, CACHE_SIZE);

     {
        CLIENT = new OkHttpClient.Builder().
                connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS).
                writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS).
                readTimeout(TIMEOUT, TimeUnit.SECONDS).
                authenticator(new Authenticator()).
                addInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR).
                cache(cache).
                addInterceptor(new Interceptor() {
                    @Override
                    public Response intercept(Chain chain) throws IOException {
                        Request request;

                        UserModel user = HelperFactory.getDatabaseHelper().getUserDao().getCurrentUser();
                        if (user != null && user.getAccess_token() != null)
                            request = chain.request().newBuilder()
                                    .addHeader("X-Auth-Token", user.getAccess_token()).build();
                        else
                            request = chain.request().newBuilder().build();

                        long t1 = System.nanoTime();
                        Logger.debug(ApiHelper.class.getName(), String.format("Sending request %s on %s%n",
                                request.url(), chain.connection()));

                        UserModel currentUser = HelperFactory.getDatabaseHelper().getUserDao().getCurrentUser();
                        if (currentUser != null)
                            Logger.debug(ApiHelper.class.getName(), "Sending request header " + request.headers().toString());

                        if (request != null && request.body() != null && request.body().contentLength() > 0) {
                            Buffer buffer = new Buffer();
                            request.body().writeTo(buffer);
                            String body = buffer.readUtf8();
                            Logger.debug(ApiHelper.class.getName(), "Sending request body " + body);
                        }

                        Response response = chain.proceed(request);
                        String msg = response.body().string();

                        long t2 = System.nanoTime();

                        Logger.debug(ApiHelper.class.getName(), String.format("Received response %s in %.1fms%nResponse code:%s%nReceived data: %s",
                                response.request().url(), (t2 - t1) / 1e6d, response.code(), msg));

                        return response.newBuilder()
                                .body(ResponseBody.create(response.body().contentType(), msg))
                                .headers(response.headers())
                                .build();
                    }
                }).build();
    }

    @NonNull
    public static MyApplication getInstance() {
        Retrofit rf = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create(new GsonBuilder()
                        .excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC)
                        .create()))
                .client(CLIENT)
                .build();

        return rf.create(MyApplication.class);
    }


}

You initialization block is non-static, but you never allocate an instance of this object, so it never gets run. 初始化块是非静态的,但是您永远不会分配此对象的实例,因此它永远不会运行。 It looks like you intended that to initialize the static member CLIENT . 看起来您打算初始化静态成员CLIENT Because this initialization ultimately depends on a Context you can't convert that to a static initialization block. 因为此初始化最终取决于Context ,所以无法将其转换为静态初始化块。 Convert it to an initialization method that takes a Context parameter. 将其转换为采用Context参数的初始化方法。 Note: I also moved cache and httpCacheDir into this method as local variables. 注意:我还将cachehttpCacheDir作为局部变量移动到此方法中。

private static boolean isNetworkAvailable(Context context) {
        ConnectivityManager connectivityManager
                = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}

// Configure access cache when offline
private static Interceptor getInterceptor(Context context) {
    return new Interceptor() {
    @Override
    //....
    }
}

private static void initClient(Context context) {
    httpCacheDirectory = File(context.getCacheDir(), "HttpCache");
    Cache cache = new Cache(httpCacheDirectory, CACHE_SIZE);
    CLIENT = new OkHttpClient.Builder().
            connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS).
            writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS).
            readTimeout(TIMEOUT, TimeUnit.SECONDS).
            authenticator(new Authenticator()).
            addInterceptor(getInterceptor((context)).
            cache(cache).
            addInterceptor(new Interceptor() {
                @Override
                public Response intercept(Chain chain) throws IOException {
                    Request request;

                    UserModel user = HelperFactory.getDatabaseHelper().getUserDao().getCurrentUser();
                    if (user != null && user.getAccess_token() != null)
                        request = chain.request().newBuilder()
                                .addHeader("X-Auth-Token", user.getAccess_token()).build();
                    else
                        request = chain.request().newBuilder().build();

                    long t1 = System.nanoTime();
                    Logger.debug(ApiHelper.class.getName(), String.format("Sending request %s on %s%n",
                            request.url(), chain.connection()));

                    UserModel currentUser = HelperFactory.getDatabaseHelper().getUserDao().getCurrentUser();
                    if (currentUser != null)
                        Logger.debug(ApiHelper.class.getName(), "Sending request header " + request.headers().toString());

                    if (request != null && request.body() != null && request.body().contentLength() > 0) {
                        Buffer buffer = new Buffer();
                        request.body().writeTo(buffer);
                        String body = buffer.readUtf8();
                        Logger.debug(ApiHelper.class.getName(), "Sending request body " + body);
                    }

                    Response response = chain.proceed(request);
                    String msg = response.body().string();

                    long t2 = System.nanoTime();

                    Logger.debug(ApiHelper.class.getName(), String.format("Received response %s in %.1fms%nResponse code:%s%nReceived data: %s",
                            response.request().url(), (t2 - t1) / 1e6d, response.code(), msg));

                    return response.newBuilder()
                            .body(ResponseBody.create(response.body().contentType(), msg))
                            .headers(response.headers())
                            .build();
                }
            }).build();
}

Then you will need to also take a Context to you getInstance method and then call initClient -- 然后你还需要将一个Context带到getInstance方法,然后调用initClient -

@NonNull
public static MyApplication getInstance(Context context) {
    initClient(context);
    Retrofit rf = new Retrofit.Builder()
            .baseUrl(baseUrl)
            .addConverterFactory(GsonConverterFactory.create(new GsonBuilder()
                    .excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC)
                    .create()))
            .client(CLIENT)
            .build();

    return rf.create(MyApplication.class);
}

You can also delete your constructor and the context data member as they are not used. 您也可以删除构造函数和context数据成员,因为它们未被使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM