gpt4 book ai didi

android - 在由 FragmentStatePagerAdapter 管理的选定 ViewPager fragment 上,UserVisibleHint 为 false

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:42:30 45 4
gpt4 key购买 nike

我在 Android 应用程序中遇到了一个非常难以诊断的问题。 getUserVisibleHint()ViewPager 中当前选择的 fragment 上返回 false,而当它应该返回 true(因为它是可见的并且被选中)时。

我将我看到的这种行为描述如下:

  • fragment 被选中并且当前显示在 ViewPager
  • ViewPager 由 FragmentStatePagerAdapter 管理
  • Fragment 先前已被选中,其状态已保存并随后由 PagerAdapter 恢复
    • viewpager 中至少有 3 个标签
    • 用户导航到选项卡 3,然后导航到选项卡 1,然后返回到选项卡 3。
  • 应用使用支持库版本 24.0.0 或更高版本

最佳答案

调试显示 FragmentStatePagerAdapter 实际上是在 setPrimaryItem(ViewGroup container, int position, Object object) 中正确设置所选选项卡的状态,但后来设置为FragmentManager#moveToState(Fragment f, int newState, int transit, int transitionStyle, boolean keepActive) 中的 false

//from FragmentManager#moveToState(Fragment f, int newState, int transit, int transitionStyle, boolean keepActive)
f.mUserVisibleHint = f.mSavedFragmentState.getBoolean(
FragmentManagerImpl.USER_VISIBLE_HINT_TAG, true);
上面的

f.mSavedFragmentState 已将可见状态保存为 false,因为它是在 fragment 不再出现在屏幕上时保存的。

所以这里的问题是状态丢失;可见状态正在 FragmentStatePagerAdapter#setPrimaryItem 中设置,但在 fragment 的 onResume 方法被调用之前丢失了一段时间。

修复

在库中修复此错误之前,覆盖 PagerAdapter 中的 setPrimaryItem 并强制首先提交任何待处理的事务。

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

@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
//Force any pending transactions to save before we set an item as primary
finishUpdate(null);
super.setPrimaryItem(container, position, object);
}

@Override
public Fragment getItem(int position) {
Fragment fragment = new DummySectionFragment();
Bundle args = new Bundle();
args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, position + 1);
fragment.setArguments(args);
return fragment;
}

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

@Override
public CharSequence getPageTitle(int position) {
return "Page " + (position + 1);
}
}

要解决此问题,FragmentStatePagerAdapter 必须在设置用户可见提示之前提交任何 fragment 事务。

FragmentStatePagerAdapter

只是为了展示 FragmentStatePagerAdapter 内部发生了什么

@Override
public Object instantiateItem(ViewGroup container, int position) {
// If we already have this item instantiated, there is nothing
// to do. This can happen when we are restoring the entire pager
// from its saved state, where the fragment manager has already
// taken care of restoring the fragments we previously had instantiated.
if (mFragments.size() > position) {
Fragment f = mFragments.get(position);
if (f != null) {
return f;
}
}

if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}

Fragment fragment = getItem(position);
if (DEBUG) Log.v(TAG, "Adding item #" + position + ": f=" + fragment);
if (mSavedState.size() > position) {
Fragment.SavedState fss = mSavedState.get(position);
if (fss != null) {
fragment.setInitialSavedState(fss);
}
}
while (mFragments.size() <= position) {
mFragments.add(null);
}
fragment.setMenuVisibility(false);
fragment.setUserVisibleHint(false);
mFragments.set(position, fragment);
mCurTransaction.add(container.getId(), fragment);

return fragment;
}

@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
Fragment fragment = (Fragment)object;
if (fragment != mCurrentPrimaryItem) {
if (mCurrentPrimaryItem != null) {
mCurrentPrimaryItem.setMenuVisibility(false);
mCurrentPrimaryItem.setUserVisibleHint(false);
}
if (fragment != null) {
fragment.setMenuVisibility(true);
fragment.setUserVisibleHint(true);
}
mCurrentPrimaryItem = fragment;
}
}

@Override
public void finishUpdate(ViewGroup container) {
if (mCurTransaction != null) {
mCurTransaction.commitNowAllowingStateLoss();
mCurTransaction = null;
}
}

关于android - 在由 FragmentStatePagerAdapter 管理的选定 ViewPager fragment 上,UserVisibleHint 为 false,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44052437/

45 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com