离线缓存 okhttp + 改造不起作用

Offline cache okhttp + retrofit not working

我正在尝试在没有可用网络时激活用于离线浏览的缓存。 不幸的是,它无法正常工作,当我调试应用程序时,正在访问拦截器或缓存。

所以我猜下面的代码有问题。

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);
    }


}

你的初始化块是非静态的,但你从来没有分配这个对象的实例,所以它永远不会得到 运行。看起来您打算初始化静态成员 CLIENT。因为此初始化最终取决于 Context,所以您无法将其转换为静态初始化块。将其转换为采用 Context 参数的初始化方法。注意:我还将 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();
}

那你还需要带一个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);
}

您还可以删除构造函数和 context 数据成员,因为它们未被使用。