ViewPager.setOffsetscreenPageLimit(0)完全无效.如何在ViewPager中一次只加载



即使我设置oViewPager.setOffsetscreenPageLimit(0),我的视图寻呼机仍然在可见页面的每侧加载1个屏幕外页面。

如何使其仅在用户滑动到页面时加载页面

如果有帮助,我的适配器:

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

}

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

这将要求您设置更高的OffScreenPageLimit,但每次看到片段时都会更新。

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

如何让它只在用户滑动到页面时加载页面?

编写自己的ViewPager。正如Jani的回答所指出的,ViewPager的屏幕外页面每侧的最小限制为1。

这是滑动动画顺利工作所必需的。否则,如果我们必须等待您为下一页设置UI,无论您需要多长时间才能建立UI,用户的滑动都将被冻结,或者滑动到空白内容。

你不能这么做。您将得到如下错误:"请求的屏幕外页面限制0太小;默认为1"。但在这里你可以找到更多关于它的信息:ViewPager.setOffsetscreenPageLimit(0)没有';t按预期工作

我使用Loader并初始化onPageSelected中每个片段的Loader。

在片段中添加此方法

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
        // load data here      resumePlayer(); 
    }else{
       // fragment is no longer visible    pausePlayer();
    }
}

有源代码

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

您可以通过复制视图寻呼机的源来自定义视图寻呼机,然后更改此方法

像这个

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

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

让我们从头开始:

viewpager的工作原理:

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

第一个解决方案:

mViewPager.setOffscreenPageLimit(0);

结果是:

请求的屏幕外页面限制0太小;默认为1

第二个解决方案:

您希望在用户实际可见时更新片段,因此请使用以下方法:

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

希望它能在未来帮助到别人!!!

经过几轮工作,我找到了解决方案。这是完美的工作。每个选项卡片段类都实现了这些代码步骤。

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

和In-onCreateView加载相同的数据或调用相同的web服务,如下面的

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

在初始化视图页面的YourMainFragment中,添加此方法以获取currentTab

public int getCurrentTab(){
        if(mViewPager != null) return mViewPager.getCurrentItem();
        else return -1;
    }

最新更新