带有 Retrofit 2 Cache-Control 的离线模式

Offline mode with Retrofit 2 Cache-Control

我正在开发一个需要离线模式的 android 应用程序,我正在使用带有缓存控制的改造 2,但面临的问题是缓存文件没有被创建,只有文件在该文件夹中创建名为 journal.I 我在这里发布我的 ApiClient.java 文件代码。

public class ApiClient {

public static final String BASE_URL = "http://www.something.com/";
private static Retrofit retrofit = null;
private static APIInterfaces apiInterface;
private  static Context mcontext=getApplicationContext();


static Interceptor OFFLINE_INTERCEPTOR = new Interceptor() {
    @Override
    public okhttp3.Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        if (!isConnected()) {
            int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale
            request = request.newBuilder()
                    .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                    .build();
        }

        return chain.proceed(request);
    }
};


static Interceptor ONLINE_INTERCEPTOR = new Interceptor() {
    @Override
    public okhttp3.Response intercept(Chain chain) throws IOException {
        okhttp3.Response response = chain.proceed(chain.request());
        int maxAge = 60; // read from cache
        return response.newBuilder()
                .header("Cache-Control", "public, max-age=" + maxAge)
                .build();
    }
};



protected static Retrofit getClient() {
    if (retrofit == null) {

        createFolder();
        Gson gson = new GsonBuilder()
                .setLenient()
                .create();


        OkHttpClient okHttpClient = new OkHttpClient
                .Builder()
                .cache(new Cache(new File(Environment.getExternalStorageDirectory() + File.separator + "something"), 10 * 1024 * 1024)) // 10 MB
                .addInterceptor(OFFLINE_INTERCEPTOR)
                .addNetworkInterceptor(ONLINE_INTERCEPTOR)
                .build();

        retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL).client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
    }
    return retrofit;
}


public static APIInterfaces getApiInterface() {
    if (apiInterface == null)
        apiInterface = ApiClient.getClient().create(APIInterfaces.class);
    return apiInterface;
}



private static boolean isConnected() {
    try {
        android.net.ConnectivityManager e = (android.net.ConnectivityManager) mcontext.getSystemService(
                Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetwork = e.getActiveNetworkInfo();
        return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
    } catch (Exception e) {
        Log.w(TAG, e.toString());
    }

    return false;
}

public  static boolean isStoragePermissionGranted() {
    if (Build.VERSION.SDK_INT >= 23) {
        if (mcontext.checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
                == PackageManager.PERMISSION_GRANTED) {
            return true;
        } else {
            ActivityCompat.requestPermissions((Activity) mcontext,
                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
            return false;
        }
    }
    else { //permission is automatically granted on sdk<23 upon installation
        return true;
    }
}



private static void createFolder() {
    if (isStoragePermissionGranted()) {
        File folder = new File(Environment.getExternalStorageDirectory() + File.separator + "Something");

        if (!folder.exists()) {
            folder.mkdir();
        }
    }
}

}

谁能解释一下上面的代码有什么问题。

当您使用拦截器更改 headers 时,它不会在调用 CacheStrategy.isCacheable() 之前进行任何调整。

尝试使用 networkInterceptors() 调用更改 interceptors()

看看这里: https://github.com/square/okhttp/wiki/Interceptors

此外,您不能使用 OkHttp 的缓存来缓存 POST 请求。您需要使用其他机制来存储它们,see this

其他机制:

有几种方法,一种可以将在线结果存储到本地数据库,如果大多数人都这样做,则可以从那里检索它,第二种选择是覆盖 OKHTTP 但这将是昂贵的就性能而言,第三个移动设备显然正在将您的 POST API 结构转换为 GET

但是,看看here它也包含一篇博客文章,这会对你有所帮助。