在网络调用之前改装2个负载缓存

Pet*_*ter 4 android retrofit2

我正在使用翻新2进行API调用,但是我的问题是API响应需要花费一些时间来显示响应,是否有可能我可以存储数据并加载该缓存并显示它,然后调用网络API。

例如:

第一次点击->进行网络呼叫-使用列表视图将输出呈现到屏幕上->将响应存储在缓存中

下次用户出现在屏幕上->加载缓存并将其呈现到屏幕上->进行网络调用->使用更改刷新适配器

我指的是要点链接之一 https://gist.github.com/Tetr4/d10c5df0ad9218f967e0

Ema*_*l S 5

是的,有很多解决方案可以做到这一点。

如果您使用RxJava(这与翻新效果很好),这就是解决方案

首先是使用concat,例如:

Observable<Data> source = Observable  
  .concat(memory, disk, network).first();
Run Code Online (Sandbox Code Playgroud)

内存,磁盘和网络都是可观察的。首先。这意味着如果缓存可用,则使用缓存,否则使用磁盘,否则使用网络。

问题在于一旦拥有缓存,它将永远不会进入网络。这就是为什么您应该这样做:

 getRemoteItems().publish { Flowable.merge(it,  getLocalItems().takeUntil(it)) }
Run Code Online (Sandbox Code Playgroud)

这样可以同时获取远程和本地数据,但是一旦获取了远程数据,就停止本地数据。您可以使用doOnSuccess使用以下命令将本地数据填充到本地数据库中

是的,有很多解决方案可以做到这一点。

首先是使用concat,例如:

Observable<Data> source = Observable  
  .concat(memory, disk, network).first();
Run Code Online (Sandbox Code Playgroud)

内存,磁盘和网络都是可观察的。首先。这意味着如果缓存可用,则使用缓存,否则使用磁盘,否则使用网络。

问题在于一旦拥有缓存,它将永远不会进入网络。这就是为什么您应该这样做:

 getRemoteItems()
        .doOnSuccess { storeToLocal(it) }
        .publish { Flowable.merge(it,  getLocalItems().takeUntil(it)) }
Run Code Online (Sandbox Code Playgroud)

这意味着它会在尝试获取缓存的同时获取远程项目。如果能够获取远程数据,它将数据存储到缓存中。

如果您使用的是不带first()的第一个示例,则在最坏的情况下它将传递3倍的Data数据,但要等到可观察到的时间结束。这意味着它将尝试内存,一旦内存调用onComplete(),它将进入磁盘。如果磁盘已完成,请尝试网络。

Observable<Data> source = Observable  
      .concat(memory, disk, network) 
Run Code Online (Sandbox Code Playgroud)


Rod*_*vão 2

您可以首先缓存所有响应:

public static Retrofit getAdapter(Context context, String baseUrl) {
    OkHttpClient.Builder okHttpClient = new OkHttpClient().newBuilder();
    Cache cache = new Cache(getCacheDir(), cacheSize);

    okHttpClient.cache(cache).build();

    Retrofit.Builder retrofitBuilder = new Retrofit.Builder();
    retrofitBuilder.baseUrl(baseUrl).client(okHttpClient);
    return retrofitBuilder.build();
}
Run Code Online (Sandbox Code Playgroud)

在下一次网络调用中,您可以检查响应是否已更改。如果是这样,那么您会得到新的响应,如果不是,则不需要刷新适配器:

if (response.isSuccessful() &&
    response.raw().networkResponse() != null &&
    response.raw().networkResponse().code() ==
       HttpURLConnection.HTTP_NOT_MODIFIED) {
    // the response hasn't changed, so you do not need to do anything
    return;
}
// otherwise, you can get the new response and refresh your adapter
...
Run Code Online (Sandbox Code Playgroud)

在@vsync 评论之后,我刚刚更新了这个答案。我希望现在好多了。


参考文献:https://android.jlelse.eu/reducing-your-networking-footprint-with-okhttp-etags-and-if-modified-since-b598b8dd81a1