ViewPager.setOffscreenPageLimit(0) has no effect a

2020-02-07 00:39发布

even when I set oViewPager.setOffscreenPageLimit(0) my view pager still loads 1 off screen page on each side of the visible page.

How do I make it only load the page when the user slides to it?

My adapter if it helps:

public class MainPagerAdapter extends FragmentPagerAdapter {
    protected static final String[] CONTENT = new String[] { "page 1", "page 2", "page 3", "page 4", };

    private int mCount = CONTENT.length;

    public MainPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        //return TestFragment.newInstance(CONTENT[position % CONTENT.length]);
        return MainFragment.newInstance(position);
    }

    @Override
    public int getCount() {
        return mCount;
    }

    @Override
    public CharSequence getPageTitle(int position) {
      return MainPagerAdapter.CONTENT[position % CONTENT.length];
    }

    public void setCount(int count) {
        if (count > 0 && count <= 10) {
            mCount = count;
            notifyDataSetChanged();
        }
    }


}

8条回答
一纸荒年 Trace。
2楼-- · 2020-02-07 01:20

add this method in fragment

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
        // load data here      resumePlayer(); 
    }else{
       // fragment is no longer visible    pausePlayer();
    }
}
查看更多
Summer. ? 凉城
3楼-- · 2020-02-07 01:23

You cant do this. You will get an error like: "Requested offscreen page limit 0 too small; defaulting to 1". But here you can find more about it: ViewPager.setOffscreenPageLimit(0) doesn't work as expected

查看更多
太酷不给撩
4楼-- · 2020-02-07 01:23

I found a solution for this after few work round. This is work perfectly. each tab fragment class implement this code steps.

 private boolean loadData = false;

 @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (this.isVisible() && isVisibleToUser ) {
            loadData = true;
            // Load your data or call web services 
            performDataRequestAsyncTask();
        }
    }

and In onCreateView Load same data or call same web service like below

     if(!loadData && YourMainFragment.yourMainFragment.getCurrentTab() == CURRENT_TAB_INDEX){
           // Load your data or call web services 
        performDataRequestAsyncTask();
      }

In YourMainFragment which you initialize your viewrpage add this method to get currentTab

public int getCurrentTab(){
        if(mViewPager != null) return mViewPager.getCurrentItem();
        else return -1;
    }
查看更多
别忘想泡老子
5楼-- · 2020-02-07 01:31

Another alternative is to use a OnPageChangeListener, and whenever a page change occurs call a refresh method in your fragments.

This will require you to set a higher OffScreenPageLimit, but the fragments will be updated every time one is brought into view.

pager.setOnPageChangeListener(new OnPageChangeListener() {

     @Override
     public void onPageSelected(int position){
         ((MyRefreshableFragment)pager.getAdapter().getItem(position)).refresh();
     }

     @Override
     public void onPageScrolled(int arg0, float arg1, int arg2) {}
     @Override
     public void onPageScrollStateChanged(int arg0) {}
  });
查看更多
做个烂人
6楼-- · 2020-02-07 01:31

How do I make it only load the page when the user slides to it?

Write your own ViewPager. As is noted by Jani's answer, ViewPager has a minimum offscreen page limit of 1 to each side.

This is required for the swiping animation to work smoothly. Otherwise, if we had to wait for you to set up the UI for the next page, the user's swipe would be frozen, or swipe to blank content, for however long it takes you to get that UI established.

查看更多
等我变得足够好
7楼-- · 2020-02-07 01:32

there are the source code

   /**
 * 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.
 *
 * <p>This is offered as an optimization. If you know in advance the number
 * of pages you will need to support or have lazy-loading mechanisms in place
 * on your pages, tweaking this setting can have benefits in perceived smoothness
 * of paging animations and interaction. If you have a small number of pages (3-4)
 * that you can keep active all at once, less time will be spent in layout for
 * newly created view subtrees as the user pages back and forth.</p>
 *
 * <p>You should keep this limit low, especially if your pages have complex layouts.
 * This setting defaults to 1.</p>
 *
 * @param limit How many pages will be kept offscreen in an idle state.
 */
public void setOffscreenPageLimit(int limit) {
    if (limit < DEFAULT_OFFSCREEN_PAGES) {//DEFAULT_OFFSCREEN_PAGES = 1
        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();
    }
}

you can custom your viewpager by copy the viewpager's source, then change this method

like this

public class LazyViewPager extends ViewGroup {
private static final String TAG = "LazyViewPager";
private static final boolean DEBUG = false;

private static final boolean USE_CACHE = false;

private static final int DEFAULT_OFFSCREEN_PAGES = 0;//change default to load one page,no offset,ViewPager is 1,so cache 2 Fragment
private static final int MAX_SETTLE_DURATION = 600; // ms
查看更多
登录 后发表回答