简体   繁体   English

ViewPager.setOffscreenPageLimit(0)完全没有效果。 如何在ViewPager中一次只加载一个页面?

[英]ViewPager.setOffscreenPageLimit(0) has no effect at all. How do I only load one page at a time in a ViewPager?

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),我的视图寻呼机仍然会在可见页面的每一侧加载1个屏幕页面。

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


}

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. 这将要求您设置更高的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) {}
  });

How do I make it only load the page when the user slides to it? 如何在用户滑动页面时仅加载页面?

Write your own ViewPager . 编写自己的ViewPager As is noted by Jani's answer, ViewPager has a minimum offscreen page limit of 1 to each side. 正如Jani的回答所述, 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. 否则,如果我们必须等待您为下一页设置UI,则用户的滑动将被冻结,或者滑动到空白内容,因为无论您花多长时间都建立了该UI。

You cant do this. 你不能这样做。 You will get an error like: "Requested offscreen page limit 0 too small; defaulting to 1". 您将收到如下错误:“请求的屏幕外页面限制0太小;默认为1”。 But here you can find more about it: ViewPager.setOffscreenPageLimit(0) doesn't work as expected 但是在这里您可以找到更多相关信息: ViewPager.setOffscreenPageLimit(0)无法正常工作

我使用一个Loader并在onPageSelected初始化每个片段的onPageSelected

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: viewpager的工作原理:

By default it keeps one item in memory either side so it does not have to create it everytime. 默认情况下,它会将一个项目保留在内存中的任何一侧,这样就不必每次都创建它。

1st Solution: 第一解决方案

mViewPager.setOffscreenPageLimit(0);

which results to: 结果是:

Requested offscreen page limit 0 too small; 请求的屏幕外页面限制0太小; defaulting to 1 默认为1

2nd Solution: 第二解决方案

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!!! 希望它能帮助将来的某个人!

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

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 和onCreateView加载相同的数据或调用同样的Web服务,如下所示

     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 在初始化viewrpage的YourMainFragment中添加此方法以获取currentTab

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM