ViewPager.setOffscreenPageLimit(0) не работает должным образом

Фрагменты, которые я использую в моем экземпляре ViewPager, довольно ресурсоемкие, поэтому я хотел бы только загружать их по одному. Когда я попробую следующее:

mViewPager.setOffscreenPageLimit(0);
mViewPager.setAdapter(mPagerAdapter);

Функция переопределения My FragmentStatePagerAdapter.getItem(int position) называется 3 раза, что и происходит при вызове mViewPager.setOffscreenPageLimit(1). Я бы ожидал, что его можно будет вызывать только один раз, потому что я указал 0 на экранных страницах.

Я считаю, что я правильно звоню, потому что, если я звоню mViewPager.setOffscreenPageLimit(2), FragmentStatePagerAdapter.getItem(int position) вызывается 5 раз, как я ожидал.

Требуется ли ViewPager минимум 1 внеэкранных страниц, или я делаю что-то неправильно здесь?

Ответ 1

Требуется ли ViewPager минимум 1 внеэкранных страниц

Да. Если я правильно читаю исходный код, вы должны получить предупреждение об этом в LogCat, например:

Requested offscreen page limit 0 too small; defaulting to 1

Ответ 2

Лучший способ, который я нашел, - setUserVisibleHint
добавьте это в свой фрагмент

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

Ответ 3

Первое добавление

   boolean _areLecturesLoaded = false;

чем

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser && !_areLecturesLoaded) {
        //Load Your Data Here like.... new GetContacts().execute();

        _areLecturesLoaded = true;
    }
else{
     }
}

Ответ 4

Вы можете попробовать следующее:

public abstract class LazyFragment extends Fragment {
    protected boolean isVisible;
    /**
     * 在这里实现Fragment数据的缓加载.
     * @param isVisibleToUser
     */
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if(getUserVisibleHint()) {
            isVisible = true;
            onVisible();
        } else {
            isVisible = false;
            onInvisible();
        }
    }
    protected void onVisible(){
        lazyLoad();
    }
    protected abstract void lazyLoad();
    protected void onInvisible(){}

Ответ 5

Альтернативное решение использует FragmentStatePagerAdapter

public static class MyAdapter extends FragmentStatePagerAdapter {
    public MyAdapter(FragmentManager fm) {
        super(fm);
    }

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

    @Override
    public Fragment getItem(int position) {
        return ArrayListFragment.newInstance(position);
    }
}

Ответ 6

ViewPager по умолчанию загружает следующую страницу (фрагмент), которую вы не можете изменить с помощью setOffscreenPageLimit (0). Но вы можете сделать что-то, чтобы взломать. Вы можете реализовать функцию onPageSelected в Activity, содержащей ViewPager. В следующем фрагменте (который вы не хотите загружать) вы пишете функцию let say showContent(), где вы вставляете весь код инициализации ресурсов и ничего не делаете перед методом onResume(). Затем вызовите функцию showViewContent() внутри onPageSelected. Надеюсь, это поможет.

Ответ 7

для функции "instantiateItem", просто подготовьте фрагмент, но не загружайте тяжелое содержимое.

Используйте "onPageChangeListener", чтобы каждый раз, когда вы переходите на определенную страницу, вы загружаете ее тяжелый контент и показываете его.

Ответ 8

Это может быть старый поток, но это, похоже, работает для меня. Переопределите эту функцию:

@Override
public void setMenuVisibility(boolean menuVisible) { 
    super.setMenuVisibility(menuVisible);

    if ( menuVisible ) {
        /**
         * Load your stuffs here.
         */
    } else  { 
        /**
         * Fragment not currently Visible.
         */
    } 
}

счастливые кодировки...

Ответ 9

У меня такая же проблема. Я нашел полезный код на этом сайте и преобразовал его.

min int для mViewPager.setOffscreenPageLimit(...); 1, поэтому, даже если вы измените его на 0, вы все равно загрузите 2 страницы.

Первое, что нужно сделать, это создать статический int, который мы назовем maxPageCount и переопределим метод getCount() для FragmentStatePagerAdapter для возврата maxPageCount:

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

Создайте статический метод, доступный из любого места в программе, которое позволит вам изменить этот maxCount:

public static void addPage(){
    maxPageCount++; //or maxPageCount = fragmentPosition+2
    mFragmentStatePagerAdapter.notifyDataSetChanged(); //notifyDataSetChanged is important here.
}

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

Надеюсь, что это поможет кому-то.