How to use addListenerIfPending

718 views Asked by At

Can someone tell me if I am using the PendingRequestListener correctly (I am using the robospice library for android)? Here is an example of my code:

I start and stop the manager per-activity: LoginActivty.java

private SpiceManager spiceManager = new SpiceManager(UncachedSpiceService.class);

    @Override
    protected void onStart() {
        spiceManager.start(this);
        super.onStart();
    }

    @Override
    protected void onStop() {
        if (spiceManager.isStarted()) {
            spiceManager.shouldStop();
        }
        super.onStop();
    }

    public SpiceManager getSpiceManager() {
        return spiceManager;
    }

In LoginFragment.java In the onClick of a 'forgot password' button I prompt the user to enter their email or id and hit submit:

mEmailOrID = input.getText().toString();

if (AppStatus.getInstance(mContext).isOnline(mContext)) {
    ((LoginActivity) getActivity()).getSpiceManager().execute(
            new RequestForgotPassword(mEmailOrID),
            mEmailOrID,
            DurationInMillis.ALWAYS_EXPIRED,
            new ForgotPasswordRequestListener());
} else {
    Toast.makeText(mContext, R.string.toast_error_web_connection, Toast.LENGTH_SHORT).show();
}

Here is the ForgotPasswordRequestListener()

public final class ForgotPasswordRequestListener implements PendingRequestListener<JSONObject> {

    @Override
    public void onRequestFailure(SpiceException spiceException) {
        if (isAdded()) {
            Toast.makeText(getActivity(), "Request failure", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onRequestSuccess(final JSONObject result) {
        if (isAdded()) {
            try {
                JSONObject response = result.getJSONObject("response");
                if (response.getString("success").matches("1")) {
                    Toast.makeText(getActivity(), "An email has been sent to your account to assist in recovering your password", Toast.LENGTH_LONG).show();
                } else {
                    Toast.makeText(getActivity(), "We don't have any record of that ID or registered email, sorry! Please try again", Toast.LENGTH_LONG).show();
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onRequestNotFound() {
        //Called if the addListenerIfPending finds no pending request.
        Toast.makeText(getActivity(), "NO REQUEST FOUND", Toast.LENGTH_LONG).show();
    }
}

The LoginFragment contains this to restart the request if necessary:

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    if (savedInstanceState != null) {
        mEmailOrID = savedInstanceState.getString(Constants.SpiceTags.LOGIN_FORGOT_PASS);
    }
}

@Override
public void onStart() {
    super.onStart();
    SpiceManager spiceManager = ((LoginActivity) getActivity()).getSpiceManager();
    spiceManager.addListenerIfPending(JSONObject.class, mEmailOrID, new ForgotPasswordRequestListener());
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    outState.putString(Constants.SpiceTags.LOGIN_FORGOT_PASS, mEmailOrID);
}

Here is the actual request, delayed 10 seconds so I have a chance to debug etc.

public class RequestForgotPassword extends SpiceRequest< JSONObject > {

    private String mEmailOrID;

    public RequestForgotPassword(String emailOrID) {
        super( JSONObject.class );

        mEmailOrID = emailOrID;
    }

    @Override
    public JSONObject loadDataFromNetwork() throws IOException {
        Ln.d( "Calling web service" );

        ServerFunctions serverFunctions = new ServerFunctions();
        SystemClock.sleep(10000);
        return serverFunctions.forgotPassword(mEmailOrID);
    }

}

I believe this code follows the samples quite closely, and I should be able to start a forgot password request, hit the home button and come back in to the app a few minutes later and the request will automatically re-try as the cache keys are the same (in my case the mEmailOrId instance variable). I am instead getting the onRequestNotFound() call-back every time. What could I be doing wrong?

Here is a link to my initial thoughts on the Robospice Google Group page.

EDIT: Here is the logcat, after I hit home while a request is pending. As you can see the pending request is there, and shortly afterwards something then kills it, so I mustn't be saving it correctly.

 D//SpiceManager.java:326﹕ 15:26:21.719 main SpiceManager stopping. Joining
 V//SpiceManager.java:767﹕ 15:26:21.738 main Cleared listeners of all requests to launch
 D//SpiceManager.java:789﹕ 15:26:21.751 main Removing listeners of pending request : CachedSpiceRequest [requestCacheKey=rjhf, cacheDuration=-1, spiceRequest=com.loylap.requester.RequestForgotPassword@43a190f8] : 1
 D//RequestProgressManager.java:147﹕ 15:26:21.764 main Removing listeners of request : CachedSpiceRequest [requestCacheKey=rjhf, cacheDuration=-1, spiceRequest=com.loylap.requester.RequestForgotPassword@43a190f8] : 1
 V//SpiceManager.java:796﹕ 15:26:21.775 main Cleared listeners of all pending requests
 D//SpiceManager.java:265﹕ 15:26:21.788 SpiceManagerThread 2 Interrupted while waiting for new request.
 D//SpiceManager.java:271﹕ 15:26:21.796 SpiceManagerThread 2 SpiceManager request runner terminated. Requests count: 0, stopped true, interrupted false
 D//SpiceManager.java:339﹕ 15:26:21.805 main Runner join time (ms) when should stop 19
 V//SpiceManager.java:1221﹕ 15:26:21.812 main Unbinding from service start.
 V//SpiceManager.java:1225﹕ 15:26:21.819 main Unbinding from service.
 D//SpiceManager.java:1227﹕ 15:26:21.831 main Unbound from service : UncachedSpiceService
 D//SpiceManager.java:345﹕ 15:26:21.841 main SpiceManager stopped.
 D/FORGOT PASSWORD﹕ rjhf
 I/Choreographer﹕ Skipped 371 frames!  The application may be doing too much work on its main thread.
 V//SpiceService.java:506﹕ 15:26:22.793 main Pending requests : 1
 V//SpiceService.java:511﹕ 15:26:22.802 main Start foreground
 V//SpiceService.java:495﹕ 15:26:22.855 main Pending requests : 1
 D//DefaultRequestRunner.java:151﹕ 15:26:24.140 Thread-59213 Network request call ended.
 D//DefaultRequestRunner.java:171﹕ 15:26:24.147 Thread-59213 Start caching content...
 D//RequestProgressManager.java:82﹕ 15:26:24.159 Thread-59213 Sending progress WRITING_TO_CACHE
 D//SpiceServiceListenerNotifier.java:146﹕ 15:26:24.167 Thread-59213 Message queue is Handler (android.os.Handler) {439d1b68}
 V//DefaultRequestListenerNotifier.java:131﹕ 15:26:24.185 main Notifying 0 listeners of progress com.octo.android.robospice.request.listener.RequestProgress@438eec90
 D//RequestProgressManager.java:82﹕ 15:26:24.210 Thread-59213 Sending progress COMPLETE
 D//SpiceServiceListenerNotifier.java:146﹕ 15:26:24.219 Thread-59213 Message queue is Handler (android.os.Handler) {439d1b68}
 V//DefaultRequestListenerNotifier.java:131﹕ 15:26:24.234 main Notifying 0 listeners of progress com.octo.android.robospice.request.listener.RequestProgress@43a0ba60
 D//SpiceServiceListenerNotifier.java:146﹕ 15:26:24.240 Thread-59213 Message queue is Handler (android.os.Handler) {439d1b68}
 V//DefaultRequestListenerNotifier.java:166﹕ 15:26:24.255 main Notifying 0 listeners of request success
 V//RequestProgressManager.java:161﹕ 15:26:24.275 Thread-59213 Removing CachedSpiceRequest [requestCacheKey=rjhf, cacheDuration=-1, spiceRequest=com.loylap.requester.RequestForgotPassword@43a190f8]  size is 1
 D//RequestProgressManager.java:91﹕ 15:26:24.287 Thread-59213 Sending all request complete.
 V//SpiceService.java:495﹕ 15:26:24.344 Thread-59213 Pending requests : 0
1

There are 1 answers

0
viduka On

addListenerIfPending() only attach listener to request for which response don't arrive yet. But response for your request probably arrive wile app was on background so you can get it from cache. As @bmurmistro says look at How to recover properly recover from an interupted uncached request using RoboSpice , it's similar problem.