ViewPager.setOffscreenPageLimit(0) не имеет никакого эффекта. Как загружать только одну страницу за один раз в ViewPager?

даже когда я устанавливаю oViewPager.setOffscreenPageLimit(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();
        }
    }


}

Ответ 1

Другой альтернативой является использование 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) {}
  });

Ответ 2

Как мне заставить загружать страницу только тогда, когда пользователь переходит к ней?

Напишите свой собственный ViewPager. Как отмечается в ответе Яни, ViewPager имеет минимальный предел страницы за пределами экрана по 1 на каждую сторону.

Это необходимо для плавной анимации прокрутки. В противном случае, если бы нам пришлось дождаться, когда вы настроите пользовательский интерфейс для следующей страницы, пользовательский салфетки будут заморожены или прокручиваются до пустого содержимого, так как вам потребуется время, чтобы установить этот пользовательский интерфейс.

Ответ 3

Вы не можете это сделать. Вы получите сообщение об ошибке: Msgstr "Требуется слишком маленькое значение экрана для экрана 0, значение по умолчанию равно 1". Но здесь вы можете найти больше об этом: ViewPager.setOffscreenPageLimit(0) не работает должным образом

Ответ 4

Я нашел решение для этого после нескольких рабочих раундов. Это прекрасно работает. каждый класс фрагментов табуляции реализует эти шаги кода.

 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 Загрузите те же данные или вызовите тот же веб-сервис, что и ниже

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

Ответ 5

Я использую Loader и запускаю загрузчики каждого фрагмента в onPageSelected.

Ответ 6

есть исходный код

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

вы можете настроить свой просмотрщик, скопировав источник viewpager, а затем измените этот метод

как это

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

Ответ 7

Я знаю, что это очень поздний ответ, но, ради Бога, вам не нужно писать свой собственный просмотрщик, как кто-то предложил.

Давайте начнем с начала:

Как работает просмотрщик:

По умолчанию он сохраняет один элемент в памяти с каждой стороны, поэтому ему не нужно создавать его каждый раз.

1-е решение:

mViewPager.setOffscreenPageLimit(0);

что приводит к:

Запрашивается ограниченный размер страницы 0 слишком мал; по умолчанию 1

2-е решение:

Вы хотите обновить фрагмент, когда он на самом деле видится пользователю, поэтому используйте метод:

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

Надеюсь, это поможет кому-то в будущем!!!

Ответ 8

добавить этот метод во фрагмент

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