【问题标题】:Offline mode with Retrofit 2 Cache-Control带有 Retrofit 2 Cache-Control 的离线模式
【发布时间】:2018-06-08 06:16:34
【问题描述】:

我正在开发一个需要离线模式的 android 应用程序,我正在使用带缓存控制的改造 2,但面临的问题是缓存文件没有被创建,并且只有在该文件夹中创建的文件被命名为 journal。我是在此处发布我的 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();
        }
    }
}

}

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

【问题讨论】:

  • 您是否尝试过离线加载数据?是成功还是失败?
  • @sreehari 缓存文件在这种情况下没有被创建如何离线加载数据....没有文件没有数据
  • @TejashwiKalpTaru 感谢您的回答,但我想知道我的代码特有的问题是什么......
  • 你试过networkInterceptors()而不是interceptors()看看这里,github.com/square/okhttp/wiki/Interceptors

标签: android retrofit2 cache-control offline-caching


【解决方案1】:

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

尝试将interceptors() 更改为networkInterceptors() 调用。

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

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

其他机制:

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

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

【讨论】:

  • 非常感谢你拯救了我的一天......问题是“无法使用 OkHttp 的缓存缓存 POST 请求”
  • @PoonamParth 欢迎 :)
  • 现在我陷入了使用哪种机制来进行发布请求缓存的问题...阅读一些堆栈溢出建议将发布请求转换为获取一个但我认为可能会有更好的答案这个.....你能推荐点什么吗???
  • @PoonamParth 使用本地数据库缓存
猜你喜欢
  • 2017-10-17
  • 2022-11-17
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
  • 2018-03-14
  • 2017-04-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多