Etienne Lawlor
Etienne Lawlor

Reputation: 6687

Retrofit 2.0 cancel a Call object

Has anyone played around with Retrofit 2.0, specifically the Call.cancel() method?

When is the best time to trigger that? I have tried calling it in onStop() of a Fragment but have run into some issues with a call being cancelled when the screen display gets turned off. Also I tried calling it in onDestroy() of a Fragment but this method does not cancel a call that get triggered in a ViewPager ( for example switching between tabs)

Does anyone have a working example of this?

I have attempted to implement this my Loop repo : https://github.com/lawloretienne/Loop

Upvotes: 16

Views: 4568

Answers (2)

Kishan Vaghela
Kishan Vaghela

Reputation: 7938

Have you try UserVisibleHint?

   @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isVisibleToUser) {
                // fragment visible to user
        }else{
           // fragment invisible 
           // you can call Call.cancel() here
        }
    }

Upvotes: 1

stkent
stkent

Reputation: 20128

The 'right' place will largely depend on your specific use-cases. As you've discovered, there's unlikely to be a one-size-fits-all solution. Here are a couple things to consider based on your stated needs:


Is cancellation of network requests when the screen is switched off a big problem for your app? Is a user likely to turn the screen off while expecting the app to continue functioning?

  • If not, you are safe to use onStop, as you've already described.
  • If so, you can move your network requests to a class that lives outside the Activity and Fragment lifecycles (e.g. using a singleton network request manager, or relying more on Service subclasses). You will then be able to handle cancellations on a case-by-case basis. For example, you would still be able to cancel requests inside lifecycle callbacks whenever you wanted to (by signaling this to the manager), but you wouldn't be required to.

With respect to cancelling network requests triggered by Fragments in a ViewPager, you might want to implement your own faux-lifecycle methods. Here's a great pattern I've used a couple of times. The gist is as follows:

  • Have all Fragments used by the ViewPager implement an interface that contains 'fake' versions of the lifecycle methods you care about.

Example:

public interface FragmentLifecycle {
    public void onStartFragment();
    public void onStopFragment();
}
  • Set an OnPageChangeListener on your ViewPager, and track the current page inside it. Whenever the page changes, call the appropriate methods on the incoming/outgoing fragments.

Example:

private OnPageChangeListener pageChangeListener = new OnPageChangeListener() {

    int currentPosition = 0;

    @Override
    public void onPageSelected(int newPosition) {
        final FragmentLifecycle fragmentToShow = (FragmentLifecycle) pageAdapter.getItem(newPosition);
        fragmentToShow.onStartFragment();

        final FragmentLifecycle fragmentToHide = (FragmentLifecycle)pageAdapter.getItem(currentPosition);
        // Cancel network requests inside this callback. It
        // corresponds to the current page moving off-screen.
        fragmentToHide.onStopFragment(); 

        currentPosition = newPosition;
    }

    @Override
    public void onPageScrolled(int arg0, float arg1, int arg2) {
        // no-op
    }

    public void onPageScrollStateChanged(int arg0) {
        // no-op
    }
};

(I updated the linked example to use onStart/onStop since you already mentioned that lifecycle pair in your question.)

Hopefully that gives you some ideas as to how best to use the new cancellation features in Retrofit 2! Let us know what you come up with.

Upvotes: 11

Related Questions