问题
I am trying to implement a very simple case using robospice: a login screen. When login button is clicked, loading animation is shown and request is made using SpiceManager.execute(..)
(without caching, of course. Since it's a login request, I need to do actual call to the server every time).
So, to handle screen rotations, etc., in Activity.onStart()
I should use SpiceManager.addListenerIfPending(..)
, and if request is actually pending, I should show loading animation without doing any real request.
The problem is: PendingRequestListener
does not have onRequestExists()
method. It only has onRequestNotFound()
.
One possible (but unsatisfactory) solution, is to draw loading screen always, then call addListenerIfPending(..)
, and then remove loading animation in onRequestNotFound()
. This creates "flickering" loading screen if there was no real request, which looks really bad. What is the proper way of implementing desired behavior?
回答1:
Ok, in case google leads anyone here. Proper solution: in reality, this functionality is already in the library. There is a method which gets called when pending request WAS found, it just does... nothing.
You need to:
Create your own interface extending
PendingRequestListener
:public interface MyPendingRequestListener<T> extends PendingRequestListener<T> { void onRequestAggregated(); }
Note: you will need to use request listeneres implementing this interface when doing requests through Robospice.
Create your own class implementing
RequestListenerNotifier
. I did this by copy-pastingDefaultRequestListenerNotifier
(I was not able to extend it because methodpost(..)
is private) because it contains porper notification implementation for other cases. For example,MyRequestListenerNotifier
.Override method
notifyListenersOfRequestAggregated
:@Override public <T> void notifyListenersOfRequestAggregated(final CachedSpiceRequest<T> request, Set<RequestListener<?>> listeners) { post(new AggregatedRunnable(listeners), request.getRequestCacheKey()); } private static class AggregatedRunnable implements Runnable { private final Set<RequestListener<?>> listeners; public AggregatedRunnable(final Set<RequestListener<?>> listeners) { this.listeners = listeners; } @Override public void run() { if (listeners == null) { return; } Ln.v("Notifying " + listeners.size() + " listeners of request aggregated"); synchronized (listeners) { for (final RequestListener<?> listener : listeners) { if (listener != null && listener instanceof MyPendingRequestListener) { Ln.v("Notifying %s", listener.getClass().getSimpleName()); ((MyPendingRequestListener<?>) listener).onRequestAggregated(); } } } } }
Extend SpiceService and override the following method (you will need to use this customized service instead of standard robospice service):
protected RequestListenerNotifier createRequestRequestListenerNotifier() { return new MyRequestListenerNotifier(); }
That's it. Now, when you use addListenerIfPending
, onRequestAggregated()
will be called when pending request IS found.
IMPORTANT NOTE: This will only work when you use Cache key when doing request. For example, you can use empty string (but NOT null) as cache key.
Example:
//doing request for the first time
spiceManager.execute(request, "", DurationInMillis.ALWAYS_EXPIRED, requestListener);
//...
//checking if request is pending e.g. when activity is restarted
spiceManager.addListenerIfPending(responseClass, "", requestListener);
来源:https://stackoverflow.com/questions/25681395/robospice-addlistenerifpending-how-do-i-know-if-request-was-found