How can I disable the preloading in a viewpager?

12,385

Solution 1

How can I disable the preloading in a ViewPager?.

it is not possible. ViewPager preloads always at least 1 page. If you don't want this behaviour you should not use the ViewPager. You could use, for instance, a RecyclerView

Old answer

you have to call setOffscreenPageLimit(1)

From the doc

Set the number of pages that should be retained to either side of the current page in the view hierarchy in an idle state. Pages beyond this limit will be recreated from the adapter when needed.

Solution 2

Well, it seems like it's a bit more complicated than one would think. The code below is an abstract class that should be implemented by your fragment. In fact it requires the following:

  1. Replace onActivityCreated with the lazyOnActivityCreated.
  2. Implement the lazyLoadData method that loads the data for the tab.
  3. After you have loaded the data or for any reason you have changed the active data call setTabDataId.

I know it sound a bit complicated but it works every time and will definitely work when setUserHint is no good.

Here is the abstract class:

public abstract class LazyFetchTabFragment extends AbstractTabFragment {

private String tabDataId;
private String activeTabDataId;

private boolean isActive = false;
private boolean isCreated = false;

@Override
public void onStop(){
    super.onStop();
    isCreated = false;
    activeTabDataId = null;
}

/**
 * An abstract method that should be called instead of {@link android.app.Fragment#onActivityCreated(Bundle)}.
 */
public abstract void lazyOnActivityCreated() throws Exception;
public abstract void lazyLoadData() throws Exception;

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    try {
        lazyOnActivityCreated();
        isCreated = true;
        loadData();
    } catch (Exception e) {
        Log.e(this.getClass().getCanonicalName() + " - "
                + Thread.currentThread().getStackTrace()[2].getMethodName(), e.toString());
    }
}

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    // When changing tabs the spinner setOnItemSelectedListener is not called,
    // so use code below to trigger loading data.
    isActive = isVisibleToUser;
    loadData();
}

private void loadData(boolean force) {
    if (isActive && isCreated && tabDataId != null &&
            (force || (activeTabDataId == null || !activeTabDataId.equals(tabDataId))))
        try {
            lazyLoadData();
            activeTabDataId = tabDataId;
        } catch (Exception ex){
            Log.e(this.getClass().getCanonicalName() + " - "
                    + Thread.currentThread().getStackTrace()[2].getMethodName(), ex.toString());
        }
}

public void setTabDataId(String tabDataId) {
    this.tabDataId = tabDataId;
}

Good luck!

Solution 3

I modify the ViewPager source code

private static final int DEFAULT_OFFSCREEN_PAGES = 0;

You can find the source in ViewPager about setOffscreenPageLimit

public void setOffscreenPageLimit(int limit) {
    if (limit < DEFAULT_OFFSCREEN_PAGES) {
        Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to " +
                DEFAULT_OFFSCREEN_PAGES);
        limit = DEFAULT_OFFSCREEN_PAGES;
    }
    if (limit != mOffscreenPageLimit) {
        mOffscreenPageLimit = limit;
        populate();
    }
}
Share:
12,385

Related videos on Youtube

Lucas Santos
Author by

Lucas Santos

Control and Automation Engineer. development skills: java architect android C/C++ ruby-rails

Updated on September 16, 2022

Comments

  • Lucas Santos
    Lucas Santos over 1 year

    How can I disable the preloading in a viewpager?.

    I have a viewpager with 3 pages. So i dont want load the next page and previously page. How can i disable that behavior?

    • ProtossShuttle
      ProtossShuttle over 8 years
      Good question! I also want to know if it's possible to load only one page at first and then cache other loaded pages.
  • Lucas Santos
    Lucas Santos almost 10 years
    Thank you! =D But OffscreenPageLimit(0) don't work because the minimum value of the parameters is 1. OffscreenPageLimit(0) throws a log in the logcat
  • G_V
    G_V over 9 years
    I hope this is because the 1 page is the actual page on display. It's sad that I need to do this because android keeps changing GUI elements on the wrong page and I'm using fragments in a ViewPager so everything has to be static to avoid OutOfMemory. I hope Android just throws out the entire GUI library at some point and starts over from scratch, everything is just awful now. I have an 800 line fragment now to be able to display maybe 15 dynamic elements.
  • ichalos
    ichalos almost 9 years
    Change the source code of what? The API itself? And how will it work when installed to a device that has the original untouched API?
  • FanaticD
    FanaticD over 8 years
    @ichalos Usually using this approach you basically create ModifiedViewPager which you further use instead of ViewPager - and it works fine. Modification suggested by does not work though.
  • Karue Benson Karue
    Karue Benson Karue almost 8 years
    This methods gives NPE because sometimes it get's called before the onCreateView. Can you handle that??
  • Travis Yim
    Travis Yim over 7 years
    Solution provided does not answer question. The original question is how to disable preloading in a ViewPager (i.e. do not load next or previous page). The solution provided does nothing as it assigns the default value of 1.
  • ichalos
    ichalos about 7 years
    I had to fully replace the answer, as it was not working properly. It will work properly now. I know it needs some polishing, but will probably help you for now!