我正在使用RoboSpice并希望在我的应用中出现以下行为:
它应该像facebook app:当你打开它时,你会立即看到一个过时的时间线,并最终收到更新。
起初我认为spiceManager.getFromCacheAndLoadFromNetworkIfExpired()
是实现这一目标的好方法,但如果数据缓存且有效,它只会返回缓存,而不会立即发出网络请求。我已经使用DurationInMillis.ALWAYS_EXPIRED
和DurationInMillis.ALWAYS_RETURNED
进行了尝试。
我应该使用getFromCache()
来检索缓存数据,然后在onRequestSuccess()
内,使用always_expired作为参数调用spiceManager.execute()
吗?或者有更好/更简单的方法来做到这一点?
提前感谢您的帮助!
[编辑] 这些链接可能会增加讨论: https://groups.google.com/forum/#!topic/robospice/n5ffupPIpkE/discussion https://groups.google.com/forum/#!topic/robospice/LtoqIXk5JpA
答案 0 :(得分:3)
我有同样的任务,并使用here的方法:
以下是示例代码
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
用于从缓存中获取和从网络获取请求。但是,我必须做一个小技巧(参见下面的 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;
...
}
}
答案 1 :(得分:2)
Aka_sh的方法有一个重要的缺点:当你的应用程序重新启动时(无论是用户还是Android),你的dataInCache标志将被重置并返回false,尽管可能有数据缓存在永久存储器中(如文件或数据库) )。
更好的解决方案是使用1.4.6-SNAPSHOT中引入的SpiceManager的isDataInCache
和getDateOfDataInCache
。这些方法检查数据在给定的有效期内是否在缓存中可用,并返回数据放入缓存的日期。
要记住一件事:两种方法都可以异步处理,然后返回Future<Boolean>
/ Future<Data>
,所以如果你想等待一个结果(它不需要很长时间才能得到它),使用Future.get()
,例如:
spiceManager.isDataInCache(MyCachedObj.class, cacheKey, DurationInMillis.ALWAYS_RETURNED).get();
答案 2 :(得分:0)
我使用以下方法来解决此问题。此外,下面的代码将解决您的活动A加载时的问题,并且您的用户在后台加载robospice的同时决定导航到活动B.当用户导航回活动A时,您的信息将可供使用(问题2)。
第1步:添加以下代码,在onStart
方法中添加PendingRequestListener
。这将允许您解决问题2,因为@Override
public void onStart() {
super.onStart();
FragmentPostActivity.spiceManagerPlaces.addListenerIfPending(Post.class, "POSTS", pendingRequestListener);
}
将侦听robospice中的所有pendingRequest并适当地处理它们。
PendingRequestListener
第2步:创建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());
}
};
。
@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();
}
第3步:添加手动方法来缓存数据,以便在应用再次启动时检索数据。下面的方法最多可以计算20个帖子,然后将它们放入缓存中。如果它少于20个帖子,它将缓存到该数量。
{{1}}
希望我对使用Robospice的这个主题有所了解,因为关于如何做到这一点的文档很少。