【问题标题】:How to fetch retrofit cache data from cache memory which contains API response in android如何从包含android中API响应的缓存中获取改造缓存数据
【发布时间】:2017-05-09 16:39:54
【问题描述】:

该类包含用于调用 API 的 APIClient 实例,但在获取缓存时存在一个问题。我想在设备未连接到网络时从缓存中获取数据。

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

【问题讨论】:

  • 为什么在检索数据时不保存数据以备后用?
  • 您能告诉我如何在改造中使用高速缓存保存数据吗?我是 Retrofit 缓存管理的新手。
  • 谢谢!!!我正在获得解决方案,但在获得响应时,我在离线模式下收到 504 错误:@Override public void onResponse(Call call, Response response) { parameters.DismissLoader();尝试 { if (response.code() == 200) { GetRegisterResponse(response.body().string()); } } catch (IOException e) { e.printStackTrace(); }
  • 表示网关超时。我的猜测是你在你的 URL 中犯了一个错误,遗漏了一个符号或空格或一些微不足道的东西。当您调试 onResponse 方法时,请查看响应对象并复制 URL。在网络浏览器中测试上述 URL,看看它是否正常工作。即你得到你想要的回应。

标签: android api response retrofit okhttp


【解决方案1】:

这是一个我也想要的解决方案,我实现了它,它可以正常工作,将数据存储在缓存中,然后获取数据。

检查下面的代码

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

}

用于在缓存中存储和获取数据

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-16
    • 2016-03-20
    • 2013-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-21
    相关资源
    最近更新 更多