Подтвердить что ты не робот

ViewPager с фрагментами - onPause(), onResume()?

При использовании ViewPager с фрагментами наши методы onPause(), onResume() не вызывается при перемещении между вкладками. Есть ли способ, который мы можем найти во фрагменте, когда мы становимся видимыми или скрытыми?

К сожалению, у меня есть логика в onResume(), onPause(), например, регистрация с помощью служб определения местоположения, которые никогда не останавливаются при переключении вкладок, потому что onPause() никогда не вызывается, пока не выйдет из всего приложения.

Спасибо

4b9b3361

Ответ 1

ViewPager поставляется с интерфейсом OnPageChangeListener. Установив несколько флагов для предыдущих и текущих страниц, вы можете эмулировать это поведение.

Ответ 2

Учитывая предыдущие решения, не совсем понятно, вот как я решил это благодаря Phix для его намека:

В обратном вызове OnPageChange():

    Fragment old_fragment = getActiveFragment(old_position);
    Fragment new_fragment = getActiveFragment(new_position);
    old_f.setUserVisibleHint(false);
    old_f.onPause();
    new_f.setUserVisibleHint(true);
    new_f.onResume();

Затем в onResume():

    if (getUserVisibleHint())
        /* resume code */

и в onPause():

    if (!getUserVisibleHint())
        /* pause code */

Вот код getActiveFragment, также избегая его поиска:

    return fragmentManager.findFragmentByTag("android:switcher:" + viewPagerId + ":" + position);

NB: Фрагмент имеет метод isVisible(), но он не кажется очень последовательным, поэтому использование UserVisibleHint.

EDIT: замените UserVisibleHint на частный флаг. Работала намного лучше!

Ответ 3

Если вы используете библиотеку поддержки Android (версия 11), вы можете использовать getUserVisibleHint() или переопределить setUserVisibleHint() для захвата видимых и скрытых изменений. Посмотрите этот пост.

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
        // do something when visible.
    }
}

Ответ 4

Решение 1:

Определите SparseArray в ваших адаптерах ViewPagers, как показано ниже. В этом массиве мы будем содержать экземпляр фрагментов.

SparseArray<Fragment> registeredFragments = new SparseArray<>();

И Override ваш метод адаптеров instantiateItem.

@Override
public Object instantiateItem(ViewGroup container, int position) {
    Fragment fragment = (Fragment) super.instantiateItem(container, position);
    registeredFragments.put(position, fragment);
    return fragment;
}

Также Override destroyItem метод вашего ViewPagers

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    registeredFragments.remove(position);
    super.destroyItem(container, position, object);
}

И определите новый метод для получения экземпляра ViewPager Fragments.

public Fragment getRegisteredFragment(int position) {
    return registeredFragments.get(position);
} 

Теперь вы можете реализовать свою логику с помощью ViewPager's OnPageChangeListener. Вот пример того, как вы можете реализовать viewpager OnPageChangeListener:

Определите целое число, чтобы сохранить текущую позицию:

int currentPos;

yourViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                // Empty method
            }

            @Override
            public void onPageSelected(int position) {
                  // This is paused fragment.
                  final Fragment pausedFragment = yourAdapter.getRegisteredFragment(currentPos);

                  // update current position value
                  currentPos = position;

                  // This is resumed fragment
                  final Fragment resumedFragment = yourAdapter.getRegisteredFragment(currentPos);
            }

            @Override
            public void onPageScrollStateChanged(int state) {
                // Empty method
            }
        });

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

currentPos = yourViewPager.getCurrentItem();

Решение 2:

Для другого решения вы можете найти ViewPager Fragments на Tag. Вы можете создать свой тег с помощью:

@NonNull
public static String generateViewPagerFragmentTag(int viewPagerId, int position) {
        final StringBuilder tagBuilder = new StringBuilder();
        tagBuilder.append("android:switcher:");
        tagBuilder.append(viewPagerId);
        tagBuilder.append(":");
        tagBuilder.append(position);
        return tagBuilder.toString();
    }

И найдите свой Fragment:

final Fragment yourFragment = getSupportFragmentManager().findFragmentByTag(generateViewPagerFragmentTag(R.id.your_viewpager, currentPos));

Изменить: Несколько лет назад, когда я искал решение для получения текущего элемента ViewPager, я попробовал UserVisibleHint в Fragments и заметил, что он не является надежным. Я не уверен, что он надежный или нет, но все же я избегаю использования.

Ответ 5

Вы можете использовать метод ниже в Fragment

public void setUserVisibleHint(boolean isVisibleToUser){

}

когда isVisibleToUser == true, фрагмент показан

Ответ 6

Немного поздно для вечеринки, но в моем текущем приложении я установил OffScreenPageLimit в 1 для моего viewpager, это означает, что фрагменты не кэшируются, и каждый раз, когда представление меняет его, он перезагружает текущий фрагмент

https://developer.android.com/reference/android/support/v4/view/ViewPager.html#getOffscreenPageLimit()

Ответ 7

Чтобы дать немного больше определения методам в savepopulation answer:

yourPager.setOnPageChangeListener(new GridViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int row, int column, float rowOffset, float columnOffset, int rowOffsetPixels, int columnOffsetPixels) {

        }

        @Override
        public void onPageSelected(int row, int column) {
            // When on page selected if position is not specific for you
            // you can find your fragment or you can switch position.
        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    });

Ответ 8

После некоторых исследований я нашел идеальное решение для этого.

когда вы инициализируете свой адаптер, сделайте это так: -

    import static androidx.fragment.app.FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT;

//(i am using androidx but if you have not yet migrated yet you can use appcompat)

    adapter = new FeedTabsPagerAdapter(getSupportFragmentManager(), BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);

После добавления этой строки вы будете получать обратные вызовы onResume() и onPause. Пожалуйста, отметьте это правильное решение, если эта проблема решена моим кодом.