简体   繁体   English

如何从包含 android 中的 API 响应的缓存中获取改造缓存数据

[英]How to fetch retrofit cache data from cache memory which contains API response in android

This class contains the APIClient instance for calling API but here there is one problem while fetching cache.此类包含用于调用 API 的 APIClient 实例,但在获取缓存时存在一个问题。 I want to fetch data from cache memory while device is not connected to network.我想在设备未连接到网络时从缓存中获取数据。

private static Retrofit retrofit = null;
private static final String CACHE_CONTROL = "Cache-Control";

public static Retrofit getClient(Context context)
{
    if (retrofit==null) {
        retrofit = new Retrofit.Builder()
                .baseUrl(URLS.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .client(provideOkHttpClient(context))
                .build();
    }
    return retrofit;
}

/**
 * Add Client for adding Authentication headers.
 * @return Retrofit
 */
public static Retrofit getAthenticationClient()
{
    if (retrofit==null) {
        retrofit = new Retrofit.Builder()
                .baseUrl(URLS.BASE_URL)
                .client(ApiIntercepters.AddAuthenticationHeader())
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    }
    return retrofit;
}

public static OkHttpClient provideOkHttpClient(Context context)
{
    return new OkHttpClient.Builder()
            .addNetworkInterceptor(provideCacheInterceptor())
            .cache( provideCache(context))
            .build();
}

private static Cache provideCache (Context context)
{
    Cache cache = null;
    try
    {
        //setup cache
        File httpCacheDirectory = new File(context.getCacheDir(), "responses");
        int cacheSize = 10 * 1024 * 1024; // 10 MiB
        cache = new Cache(httpCacheDirectory, cacheSize);

    }
    catch (Exception e)
    {
        Log.e( "Injector :-> ", "Could not create Cache!" );
    }
    return cache;
}

public static Interceptor provideCacheInterceptor ()
{
    return new Interceptor()
    {
        @Override
        public Response intercept (Chain chain) throws IOException
        {
            Response originalResponse = chain.proceed(chain.request());
            if (RetrofitDemoApp.hasNetwork()) {
                int maxAge = 60; // read from cache for 1 minute
                return originalResponse.newBuilder()
                        .header("Cache-Control", "public, max-age=" + maxAge)
                        .build();
            } else {
                int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale
                return originalResponse.newBuilder()
                        .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                        .build();
            }
        }
    };
}

Here is a solution I also want the same and I implement it and its works properly for storing data in the cache and then fetching the data.这是一个我也想要的解决方案,我实现了它并且它可以正常工作以将数据存储在缓存中然后获取数据。

Check this below code检查下面的代码

CacheManager.java缓存管理器

 public class CacheManager {

    private Context context;
    private static final String TAG = CacheManager.class.getSimpleName();

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

    public void writeJson(Object object, Type type, String fileName) {
        File file = new File(context.getCacheDir(), fileName);
        OutputStream outputStream = null;
        Gson gson = new GsonBuilder().enableComplexMapKeySerialization().setPrettyPrinting().create();
        try {
            outputStream = new FileOutputStream(file);
            BufferedWriter bufferedWriter;
            if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream,
                        StandardCharsets.UTF_8));
            } else {
                bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));
            }

            gson.toJson(object, type, bufferedWriter);
            bufferedWriter.close();

        } catch (FileNotFoundException e) {
            Log.i(TAG,""+e);
        } catch (IOException e) {
            Log.i(TAG,""+e);
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.flush();
                    outputStream.close();
                } catch (IOException e) {
                    Log.i(TAG,""+e);
                }
            }
        }

    }


    public Object readJson(Type type, String fileName) {
        Object jsonData = null;

        File file = new File(context.getCacheDir(), fileName);
        InputStream inputStream = null;
        Gson gson = new GsonBuilder().enableComplexMapKeySerialization().setPrettyPrinting().create();
        try {
            inputStream = new FileInputStream(file);
            InputStreamReader streamReader;
            if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                streamReader = new InputStreamReader(inputStream,
                        StandardCharsets.UTF_8);
            } else {
                streamReader = new InputStreamReader(inputStream, "UTF-8");
            }

            jsonData = gson.fromJson(streamReader, type);
            streamReader.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
            if (DEBUG) Log.e(TAG, "loadJson, FileNotFoundException e: '" + e + "'");
        } catch (IOException e) {
            e.printStackTrace();
            if (DEBUG) Log.e(TAG, "loadJson, IOException e: '" + e + "'");
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    if (DEBUG) Log.e(TAG, "loadJson, finally, e: '" + e + "'");
                }
            }
        }
        return jsonData;
    }

}

For store and fetch data in the cache用于在缓存中存储和获取数据

MainActivity.java主活动.java


if (checkInternetConnection(getContext())) {
            progressBar.setVisibility(View.VISIBLE);
            Api mApiService = RetrofitClient.getClient(Api.BASE_URL).create(Api.class);

            Call<ApiModel> call = mApiService.getCountry();

            call.enqueue(new Callback<ApiModel>() {
                @Override
                public void onResponse(Call<ApiModel> call, Response<ApiModel> response) {
                    countryList = response.body();

                    countryListData = countryList.data;


                    CacheManager cacheManager = new CacheManager(MainActivity.this);

                    //store data in cache
                    Type type = new TypeToken<ApiModel>() {
                    }.getType();
                    cacheManager.writeJson(response.body(), type, "latest.json");

                    adapter = new MyListAdapter(getApplicationContext(), countryListData);
                    LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplicationContext());
                    recyclerView.setHasFixedSize(true);
                    recyclerView.setLayoutManager(linearLayoutManager);
                    recyclerView.setAdapter(adapter);

                    progressBar.setVisibility(View.GONE);
                    Log.i(TAG, "onResponse: SuccessFull");

                }

                @Override
                public void onFailure(Call<ApiModel> call, Throwable t) {
                    Toast.makeText(getApplicationContext(), "An error has occurred", Toast.LENGTH_LONG).show();

                    //api failed to return data due to network problem or something else, display data from cache file
                    Type type = new TypeToken<ApiModel>() {
                    }.getType();
                    countryList = (ApiModel) cacheManager.readJson(type, "latest.json");


                    Log.i(TAG, "onFailure: " + t);
                    progressBar.setVisibility(View.GONE);
                }

            });
        } else {

            //No internet connected then fetch data if exists
            Type type = new TypeToken<ApiModel>() {
            }.getType();
            countryList = (ApiModel) cacheManager.readJson(type, "latest.json");
            System.out.println("cacheData" + countryList.data.get(1));
            if (countryList != null) {
                countryListData = countryList.data;
                adapter = new MyListAdapter(getApplicationContext(), countryListData);
                LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplicationContext());
                recyclerView.setHasFixedSize(true);
                recyclerView.setLayoutManager(linearLayoutManager);
                recyclerView.setAdapter(adapter);
            }
        }

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

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