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?

+1


source to share


1 answer


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-paste DefaultRequestListenerNotifier

    (I couldn't extend it because the method post(..)

    is private) because it contains the porter notification implementation for other cases. Eg 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 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);

      

0


source







All Articles