setoffscreenlimit(0)没有任何影响。如何在ViewPager中每次只加载一个页面?

时间:2022-01-11 21:46:40

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

甚至当我设置oViewPager.setOffscreenPageLimit(0)时,我的视图pager仍然会在可视页面的每一侧加载一个屏幕页面。

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();
        }
    }


}

6 个解决方案

#1


5  

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

另一种选择是使用OnPageChangeListener,当发生页面更改时,在片段中调用refresh方法。

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) {}
  });

#2


3  

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.

编写自己的:viewpage。正如贾尼的回答所指出的,ViewPager对每一方的屏幕外页面限制最小为1。

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.

这是swiping动画顺利工作所需要的。否则,如果我们不得不等待您为下一页设置UI,用户的滑动将被冻结,或向空白内容滑动,无论您花多长时间来创建UI。

#3


1  

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

你不能这样做。您将得到这样的错误:“请求的屏幕外页面限制0太小;违约1”。但是在这里你可以找到更多关于它的信息:viewpage . setoffscreenlimit(0)并没有像预期的那样工作

#4


0  

I use a Loader and init the loaders of each fragment in the onPageSelected.

我使用一个加载程序并初始化所选onpagesselected中的每个片段的加载程序。

#5


0  

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

您可以通过复制viewpager的源代码来自定义viewpager,然后更改此方法

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

#6


-1  

I know this is very late answer but for God's sake you do not have to write your own viewpager as someone suggested.

我知道这是一个很晚的回答,但看在上帝的份上,你不必像别人建议的那样写你自己的viewpager。

Lets take things from start:

让我们从头开始:

How viewpager works:

:viewpage的工作原理:

By default it keeps one item in memory either side so it does not have to create it everytime.

默认情况下,它会在内存中保留一个条目,这样它就不必每次都创建它。

1st Solution:

解决方案1:

mViewPager.setOffscreenPageLimit(0);

which results to:

结果:

Requested offscreen page limit 0 too small; defaulting to 1

请求的离线页面限制太小;默认为1

2nd Solution:

解决方案2:

You want to update the Fragment when it is actually visible to the user so use the method:

你想要在用户可以看到的时候更新片段,所以使用以下方法:

@Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isVisibleToUser) {
           //Do something like 
           //adapter.notifyDataSetChanged();
        }
    }

Hope it helps someone in the future!!!

希望它对未来的人有所帮助!!

#1


5  

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

另一种选择是使用OnPageChangeListener,当发生页面更改时,在片段中调用refresh方法。

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) {}
  });

#2


3  

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.

编写自己的:viewpage。正如贾尼的回答所指出的,ViewPager对每一方的屏幕外页面限制最小为1。

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.

这是swiping动画顺利工作所需要的。否则,如果我们不得不等待您为下一页设置UI,用户的滑动将被冻结,或向空白内容滑动,无论您花多长时间来创建UI。

#3


1  

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

你不能这样做。您将得到这样的错误:“请求的屏幕外页面限制0太小;违约1”。但是在这里你可以找到更多关于它的信息:viewpage . setoffscreenlimit(0)并没有像预期的那样工作

#4


0  

I use a Loader and init the loaders of each fragment in the onPageSelected.

我使用一个加载程序并初始化所选onpagesselected中的每个片段的加载程序。

#5


0  

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

您可以通过复制viewpager的源代码来自定义viewpager,然后更改此方法

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

#6


-1  

I know this is very late answer but for God's sake you do not have to write your own viewpager as someone suggested.

我知道这是一个很晚的回答,但看在上帝的份上,你不必像别人建议的那样写你自己的viewpager。

Lets take things from start:

让我们从头开始:

How viewpager works:

:viewpage的工作原理:

By default it keeps one item in memory either side so it does not have to create it everytime.

默认情况下,它会在内存中保留一个条目,这样它就不必每次都创建它。

1st Solution:

解决方案1:

mViewPager.setOffscreenPageLimit(0);

which results to:

结果:

Requested offscreen page limit 0 too small; defaulting to 1

请求的离线页面限制太小;默认为1

2nd Solution:

解决方案2:

You want to update the Fragment when it is actually visible to the user so use the method:

你想要在用户可以看到的时候更新片段,所以使用以下方法:

@Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isVisibleToUser) {
           //Do something like 
           //adapter.notifyDataSetChanged();
        }
    }

Hope it helps someone in the future!!!

希望它对未来的人有所帮助!!