4

我正在使用 RoboSpice 并希望在我的应用程序中具有以下行为:

  • 用户启动需要来自服务器的数据的活动
  • spiceManager 检查数据是否被缓存,如果是则返回。
  • 无论是否返回了缓存数据,都会向服务器发出请求
  • 当新数据从服务器到达时,我用它更新 UI(如果活动仍然处于活动状态)

它应该类似于 facebook 应用程序:当您打开它时,您会立即看到一个过时的时间线,并最终收到更新。

起初我认为spiceManager.getFromCacheAndLoadFromNetworkIfExpired()这是实现这一点的好方法,但如果数据被缓存并且有效,它只是返回缓存而不在它之后立即发出网络请求。DurationInMillis.ALWAYS_EXPIRED我用和都试过了DurationInMillis.ALWAYS_RETURNED

我应该使用getFromCache()来检索缓存的数据,然后从内部onRequestSuccess()调用spiceManager.execute()always_expired 作为参数吗?或者有更好/更简单的方法来做到这一点?

提前感谢您的帮助!

[编辑] 这些链接可能会添加到讨论中: https ://groups.google.com/forum/#!topic/robospice/n5ffupPIpkE/discussion https://groups.google.com/forum/#!topic/robospice/ LtoqIXk5JpA

4

3 回答 3

3

我从这里有同样的任务和使用的方法:

  1. 从缓存中加载视图数据(如果存在)
  2. 同时,触发从网络加载新版本的请求。如果数据已更改,请更新视图。

这是示例代码

SpecialOffersRequest request = new SpecialOffersRequest();
spiceManager.getFromCache(SpecialOffer.List.class, request.getCacheKey(), ALWAYS_RETURNED, new SpecialOffersRequestListener());
spiceManager.execute(request, request.getCacheKey(), request.getCacheExpiryDuration(), new SpecialOffersRequestListener());

如您所见,一个SpecialOffersRequestListener用于 get-from-cache 和 get-from-network 请求。但是,我不得不做一个小技巧(请参阅下面的dataInCache用法)来处理离线情况,并且如果缓存中有要显示的内容,则不必担心用户“无连接”:

private final class SpecialOffersRequestListener implements RequestListener<SpecialOffer.List> {
    @Override
    public void onRequestFailure(SpiceException spiceException) {
        if (spiceException instanceof NoNetworkException && dataInCache) {
            // Ignore network problems if there is some data in the cache.
            return;
        }

        ActionHelper.showError(getActivity(), "Failed to load special offers.", spiceException);
    }

    @Override
    public void onRequestSuccess(SpecialOffer.List result) {
        dataInCache = true;
        ...
    }
}
于 2014-05-25T12:44:36.367 回答
2

Aka_sh 的方法有一个重要缺点:当您的应用程序重新启动(由用户或 Android)重新启动时,您的 dataInCache 标志将被重置并返回 false,尽管可能有数据缓存在永久存储(如文件或数据库)中。

更好的解决方案是使用 SpiceManagerisDataInCachegetDateOfDataInCache在 1.4.6-SNAPSHOT 中引入。这些方法检查缓存中的数据是否在给定的有效期内可用,并返回数据放入缓存的日期。

要记住的一件事:两种方法都可以异步处理并且它们返回Future<Boolean>/ Future<Data>,所以如果你只想等待结果(得到它应该不会花很长时间),使用Future.get(),例如:

spiceManager.isDataInCache(MyCachedObj.class, cacheKey, DurationInMillis.ALWAYS_RETURNED).get();
于 2014-06-16T08:58:38.187 回答
0

我使用了以下方法来解决这个问题。此外,当您的活动 A 正在加载并且您的用户决定同时导航到活动 B 而 robospice 在后台加载时,下面的代码将解决该问题。当用户导航回活动 A 时,您的信息将可供使用(问题 2)。

步骤 1:添加以下代码以PendingRequestListeneronStart方法中添加一个。这将允许您解决问题 2,因为PendingRequestListener它将侦听 robospice 中的所有 pendingRequest 并适当地处理它们。

@Override
public void onStart() {
    super.onStart();
    FragmentPostActivity.spiceManagerPlaces.addListenerIfPending(Post.class, "POSTS", pendingRequestListener);
}

第 2 步:创建您的PendingRequestListener.

PendingRequestListener pendingRequestListener = new PendingRequestListener() {
    @Override 
    public void onRequestNotFound() {
    //This is when no request is found at all - this method will be triggered. Notice that I have
    //placed this method within the onStart method which means that when your app onStarts - when you 
    //click on the app icon on your phone, this method will actually be triggered so therefore it will first
    //get the data from cache by using the cacheKey "POSTS", then it will trigger a separate spiceRequest for network
    //operations to fetch the data from the server. Notice that the second spiceRequest does not have a cacheKey.
    //The reason is that we are not going to return back the results of the network operations - we will return
    //the results of our cache that we will manually create at a later stage
        PostSpiceRequest postSpiceRequest = new PostSpiceRequest(getActivity(), postid);
        FragmentPostActivity.spiceManagerPlaces.getFromCache(EmbedPost.class, "POSTS", DurationInMillis.ONE_WEEK, new PostListener());
        FragmentPostActivity.spiceManagerPlaces.execute(PostSpiceRequest,new PostListener());
    }

    @Override
    public void onRequestFailure(SpiceException spiceException) {
    //This is if your request failed when you navigate back to Activity A from Activity B
        Log.e("PendingRequestRS", "request failed for pending requests");

    }

    @Override
    public void onRequestSuccess(Object o) {
        //This is if your request succeed when you navigate back to Activity A from Activity B
        Log.e("PendingRequestRS", "pending request successful");
        FragmentPostActivity.spiceManagerPlaces.getFromCache(Post.class, "POSTS", DurationInMillis.ONE_WEEK, new PostListener());
    }
};

第 3 步:添加手动方法来缓存您的数据,以便在您的应用再次启动时可以检索到这些数据。下面的方法最多统计 20 个帖子,然后将它们放入缓存中。如果少于 20 个帖子,它将缓存到该数量。

@Override
public void onPause() {
    super.onPause();
    //If you are using a spiceManager from your activity class, you will needs to put this code into onPause and not in onStop. 
    //Inside your activity, you would have stopped the spicemanager in onStop, which means that your cache would not be stored
    //at all.
    //If you are using a spiceManager in your fragment class, you are free to put this code within your onStop method but make
    //sure that it is place in front of the spiceManager.onStop() so that the method will execute before it spicemanager is stopped

    LinkedList<Post> cachedPosts = new LinkedList<>();
    if (posts.size() > 20) {
        for (int i = 0; i <= 20; i++) {
            cachedPosts.add(posts.get(i));
        }
    } else {
        for (int i = 0; i < posts.size(); i++) {
            cachedPosts.add(posts.get(i));
        }
    }
    PostActivity.spiceManager.removeDataFromCache(Post.class, "POSTS");
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                FragmentPostActivity.spiceManagerPlaces.putDataInCache("POSTS", cachedPosts);
            } catch (CacheSavingException e) {
                e.printStackTrace();
            } catch (CacheCreationException e) {
                e.printStackTrace();
            }
        }
    }).start();
}

希望我已经对使用 Robospice 的这个主题有所了解,因为关于如何完成的文档很少。

于 2015-12-29T17:43:07.930 回答