问题:一个viewpager2使用了FragmentStateAdapter,当系统配置发生变化(切换横竖屏、切换深色模式、切换语言),会多出fragment实例,每切一次就会多一次。查看日志每次切换后获取fragment的时候,都会重新走FragmentStateAdapter的createFragment。而之前已经生成的fragment都会重建。所以造成上面的现象和问题。

原因:这个viewpager2是动态通过代码new创建的,改成直接写在xml布局中就正常了(一般写在xml中都会加一个id的)

根因:只有绑定id的viewpager2才能正常同步fragment。从xml加载的也需要加id才能。代码动态创建的,设置id后也能正确。

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

FragmentStateAdapter源码显示,只有mFragments不包含的时候,才会从createFragment拿

@Override
public final void restoreState(@NonNull Parcelable savedState) {
    if (!mSavedStates.isEmpty() || !mFragments.isEmpty()) {
        throw new IllegalStateException(
                "Expected the adapter to be 'fresh' while restoring state.");
    }

    Bundle bundle = (Bundle) savedState;
    if (bundle.getClassLoader() == null) {
        /** TODO(b/133752041): pass the class loader from {@link ViewPager2.SavedState } */
        bundle.setClassLoader(getClass().getClassLoader());
    }

    for (String key : bundle.keySet()) {
        if (isValidKey(key, KEY_PREFIX_FRAGMENT)) {
            long itemId = parseIdFromKey(key, KEY_PREFIX_FRAGMENT);
            Fragment fragment = mFragmentManager.getFragment(bundle, key);
            mFragments.put(itemId, fragment);
            continue;
        }

        if (isValidKey(key, KEY_PREFIX_STATE)) {
            long itemId = parseIdFromKey(key, KEY_PREFIX_STATE);
            Fragment.SavedState state = bundle.getParcelable(key);
            if (containsItem(itemId)) {
                mSavedStates.put(itemId, state);
            }
            continue;
        }

        throw new IllegalArgumentException("Unexpected key in savedState: " + key);
    }

    if (!mFragments.isEmpty()) {
        mHasStaleFragments = true;
        mIsInGracePeriod = true;
        gcFragments();
        scheduleGracePeriodEnd();
    }
}

然后可以看见除了ensureFragment,只有在restoreState这个地方mFragments才会存fragment。关键是要从savedState拿到fragment。

继续跟源码可以发现adapter的restoreState方法是在viewpager2的restorePendingState方法中被调用的,其中传递的参数是mPendingAdapterState,继续看看mPendingAdapterState哪儿来的

@Override
protected void onRestoreInstanceState(Parcelable state) {
    if (!(state instanceof SavedState)) {
        super.onRestoreInstanceState(state);
        return;
    }

    SavedState ss = (SavedState) state;
    super.onRestoreInstanceState(ss.getSuperState());
    mPendingCurrentItem = ss.mCurrentItem;
    mPendingAdapterState = ss.mAdapterState;
}

mPendingAdapterState来自于viewpager2的onRestoreInstanceState。

protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
    if (mID != NO_ID) {
        Parcelable state = container.get(mID);
        if (state != null) {
            // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
            // + ": " + state);
            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
            onRestoreInstanceState(state);
            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
                throw new IllegalStateException(
                        "Derived class did not call super.onRestoreInstanceState()");
            }
        }
    }
}

可以看见只有当有id的时候才会执行onRestoreInstanceState

标签: none

已有 5 条评论

  1. 新车首发,新的一年,只带想赚米的人coinsrore.com

  2. 华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
    华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
    华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
    华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
    华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
    华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
    华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
    华纳公司合作开户所需材料?电话号码15587291507 微信STS5099

  3. 华纳公司开户注册指南?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】

  4. 华纳东方明珠客服电话是多少?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
    华纳东方明珠开户专线联系方式?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
    如何联系华纳东方明珠客服?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
    华纳东方明珠官方客服联系方式?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
    华纳东方明珠客服热线?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
    华纳东方明珠开户客服电话?(▲182(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
    华纳东方明珠24小时客服电话?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
    华纳东方明珠客服邮箱?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
    华纳东方明珠官方客服在线咨询?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
    华纳东方明珠客服微信?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】

  5. 东方明珠客服开户联系方式【182-8836-2750—】?μ- cxs20250806
    东方明珠客服电话联系方式【182-8836-2750—】?- cxs20250806】
    东方明珠开户流程【182-8836-2750—】?薇- cxs20250806】
    东方明珠客服怎么联系【182-8836-2750—】?薇- cxs20250806】

添加新评论