Как получить фрагмент по тегу в ViewPager2

Мне сказали использовать переопределение createFragment для FragmentStateAdapter, чтобы получить текущий фрагмент по индексу.

Так выглядит мой адаптер.

class AddRestaurantPagerAdapter(fragmentManager: FragmentManager, lifecycle: Lifecycle) :
    FragmentStateAdapter(fragmentManager, lifecycle) {
    private var fragments = listOf<Fragment>(
        FragmentA.newInstance(),
        FragmentB.newInstance(),
        FragmentC.newInstance(),
        FragmentD.newInstance()
    )

    override fun getItemCount() = 4
    override fun createFragment(position: Int) =
        fragments[position]

}

Это работает нормально, пока мы не принудительно активируем onSaveInstance / OnRestoreInstance для этого действия / фрагмента.

ViewPager2 перезагружает на нем уже существующие фрагменты, и нам нужен способ получить к нему доступ. Об этом свидетельствует следующий LOC в классе FragmentStateAdapter

private void ensureFragment(int position) {
        long itemId = getItemId(position);
        if (!mFragments.containsKey(itemId)) {
            // TODO(133419201): check if a Fragment provided here is a new Fragment
            Fragment newFragment = createFragment(position);
            newFragment.setInitialSavedState(mSavedStates.get(itemId));
            mFragments.put(itemId, newFragment);
        }
    }

После воссоздания активности / фрагмента вы обнаружите, что блок this If никогда не выполняется, потому что mFragments уже содержит фрагмент, добавленный до того, как действие было собрано.

Поэтому мне было интересно, как следует извлекать фрагменты уже в viewpager2


person Muhammad Ahmed AbuTalib    schedule 23.11.2019    source источник
comment
Вы нашли для этого какое-нибудь решение?   -  person Sai    schedule 03.07.2020


Ответы (1)


Если вы посмотрите на этот метод,

/**
 * @param holder that has been bound to a Fragment in the {@link #onBindViewHolder} stage.
 */
@SuppressWarnings("WeakerAccess") // to avoid creation of a synthetic accessor
void placeFragmentInViewHolder(@NonNull final FragmentViewHolder holder) {
    Fragment fragment = mFragments.get(holder.getItemId());
    if (fragment == null) {
        throw new IllegalStateException("Design assumption violated.");
    }
    FrameLayout container = holder.getContainer();
    View view = fragment.getView();

    /*
    possible states:
    - fragment: { added, notAdded }
    - view: { created, notCreated }
    - view: { attached, notAttached }

    combinations:
    - { f:added, v:created, v:attached } -> check if attached to the right container
    - { f:added, v:created, v:notAttached} -> attach view to container
    - { f:added, v:notCreated, v:attached } -> impossible
    - { f:added, v:notCreated, v:notAttached} -> schedule callback for when created
    - { f:notAdded, v:created, v:attached } -> illegal state
    - { f:notAdded, v:created, v:notAttached } -> illegal state
    - { f:notAdded, v:notCreated, v:attached } -> impossible
    - { f:notAdded, v:notCreated, v:notAttached } -> add, create, attach
     */

    // { f:notAdded, v:created, v:attached } -> illegal state
    // { f:notAdded, v:created, v:notAttached } -> illegal state
    if (!fragment.isAdded() && view != null) {
        throw new IllegalStateException("Design assumption violated.");
    }

    // { f:added, v:notCreated, v:notAttached} -> schedule callback for when created
    if (fragment.isAdded() && view == null) {
        scheduleViewAttach(fragment, container);
        return;
    }

    // { f:added, v:created, v:attached } -> check if attached to the right container
    if (fragment.isAdded() && view.getParent() != null) {
        if (view.getParent() != container) {
            addViewToContainer(view, container);
        }
        return;
    }

    // { f:added, v:created, v:notAttached} -> attach view to container
    if (fragment.isAdded()) {
        addViewToContainer(view, container);
        return;
    }

    // { f:notAdded, v:notCreated, v:notAttached } -> add, create, attach
    if (!shouldDelayFragmentTransactions()) {
        scheduleViewAttach(fragment, container);
        mFragmentManager.beginTransaction()
                .add(fragment, "f" + holder.getItemId())
                .setMaxLifecycle(fragment, STARTED)
                .commitNow();
        mFragmentMaxLifecycleEnforcer.updateFragmentMaxLifecycle(false);
    } else {
        if (mFragmentManager.isDestroyed()) {
            return; // nothing we can do
        }
        mLifecycle.addObserver(new LifecycleEventObserver() {
            @Override
            public void onStateChanged(@NonNull LifecycleOwner source,
                    @NonNull Lifecycle.Event event) {
                if (shouldDelayFragmentTransactions()) {
                    return;
                }
                source.getLifecycle().removeObserver(this);
                if (ViewCompat.isAttachedToWindow(holder.getContainer())) {
                    placeFragmentInViewHolder(holder);
                }
            }
        });
    }
}

Это tag "f" + holder.getItemId().

@Override
    public long getItemId(int position) {
        return position;
    }

getItemId(int postion) по умолчанию возвращает позицию. но если вы переопределите этот метод.

int postionOfTheFragmentYouWantToGet=0;
Fragment page = getSupportFragmentManager().findFragmentByTag("f" + postionOfTheFragmentYouWantToGet);
person rahat    schedule 24.01.2021