Robospice - addListenerIfPending - how to know if a request was found?
I am trying to implement a very simple case using robospice: login screen. When the login button is clicked, a loading animation is shown and the request is made with SpiceManager.execute(..)
(no caching, of course. Since this is a login request, I need to make an actual call to the server every time).
So, for handling screen rotations, etc. in Activity.onStart()
i should use SpiceManager.addListenerIfPending(..)
, and if the request is really expecting i should show the loading animation without a real request.
Problem: PendingRequestListener
has no method onRequestExists()
. It only has onRequestNotFound()
.
One possible (but unsatisfactory) solution is to draw the loading screen always, then invoke addListenerIfPending(..)
and then remove the loading animation in onRequestNotFound()
. This creates a "flickering" loading screen if there is no real request, which looks very bad. What is the proper way to implement the desired behavior?
source to share
Ok, in case Google brings someone here. Correct solution: in fact, this functionality is already in the library. There is a method that gets called when a pending WAS request is found, it just does ... nothing.
You need:
-
Create your own interface extending
PendingRequestListener
:public interface MyPendingRequestListener<T> extends PendingRequestListener<T> { void onRequestAggregated(); }
Note. When making requests through Robospice, you will need to use listeneres requests that implement this interface.
-
Create your own class implementing
RequestListenerNotifier
. I did it by copy-pasteDefaultRequestListenerNotifier
(I couldn't extend it because the methodpost(..)
is private) because it contains the porter notification implementation for other cases. EgMyRequestListenerNotifier
. -
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 configured service instead of the default robospice service):
protected RequestListenerNotifier createRequestRequestListenerNotifier() { return new MyRequestListenerNotifier(); }
What is it. Now that you use addListenerIfPending
, onRequestAggregated()
will be called when a pending request is pending.
IMPORTANT NOTE: This will only work when using the cache key when making the request. For example, you can use an empty string (but NOT null) as the 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);
source to share