在androidx.fragment.app.Fragment中,setUserVisibleHint()被弃用了,并且没有被执行,为什么?

in androidx.fragment.app.Fragment,setUserVisibleHint()is Deprecated,and not executed,why?

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (getUserVisibleHint()) {
        isVisible = true;
        onVisible();
    } else {
        isVisible = false;
        onInVisible();
    }
}

发现这部分代码没有执行

现在 AndroidX 方法 setUserVisibleHint(boolean isVisibleToUser) 已弃用,如果您查看文档,它会说:

You can now set a max Lifecycle state for a Fragment by calling setMaxLifecycle() on a FragmentTransaction. This replaces the now deprecated setUserVisibleHint(). FragmentPagerAdapter and FragmentStatePagerAdapter have a new constructor that allows you to switch to the new behavior.

所以基本上当你在 FragmentTransaction 中使用这种方法时:

.getSupportFragmentManager()
            .beginTransaction()
            .setMaxLifecycle(fragment, Lifecycle.State.STARTED);

等同于 setUserVisibleHint(false) 并且:

.getSupportFragmentManager()
            .beginTransaction()
            .setMaxLifecycle(fragment, Lifecycle.State.RESUMED);

相当于:setUserVisibleHint(true)

他们刚刚在 Fragments 中更改了 API。

如果使用此方法限制片段生命周期:

You can now set a max Lifecycle state for a Fragment by calling setMaxLifecycle() on a FragmentTransaction. This replaces the now deprecated setUserVisibleHint().

来源:https://developer.android.com/jetpack/androidx/releases/fragment#1.1.0-alpha07 .

如果您需要此方法,因为您试图检测哪个片段当前在 ViewPager 中可见。您现在可以只使用 onResumeonPause 方法,但在此之前您应该更改 FragmentPagerAdapter 构造函数中的默认行为。

像这样:

FragmentPagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT)

编辑: 因为 FragmentPagerAdapter 也被弃用了,所以现在最好使用 ViewPager2。 在 ViewPager2 的情况下,这是默认行为,我们可以使用 onResumeonPause 方法来了解哪个片段当前可见。

此答案假定您使用的是 FragmentStatePagerAdapter

androidx.fragment 的新版本中(从 1.1.0+ 开始),如果您的 FragmentStatePagerAdapter 使用由 [=16 指定的旧行为,Fragment.setUserVisibleHint 仍将被调用=].

如果您构建了 FragmentStatePagerAdapter 并通过了 BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT,那么 Fragment.setUserVisibleHint 将不再在 FragmentStatePagerAdapter.instantiateItem 中被调用。

注意: 如果您在 FragmentStatePagerAdapter 中指定了 BEHAVIOR_SET_USER_VISIBLE_HINT,您仍然可以调用已弃用的 Fragment.getUserVisibleHint,但请注意将 return true 即使 Fragment.isResumed() 将 return false.


androidx 项目是开源的。查看master上的最新代码,可以看到在instantiateItem里面的setUserVisibleHint周围增加了一个ifhttps://android.googlesource.com/platform/frameworks/support/+/androidx-master-dev/fragment/fragment/src/main/java/androidx/fragment/app/FragmentStatePagerAdapter.java#195

  • TL;DR:

1.0.x:

fragment.setMenuVisibility(false);
fragment.setUserVisibleHint(false);

1.1.0+:

fragment.setMenuVisibility(false);
if (mBehavior == BEHAVIOR_SET_USER_VISIBLE_HINT) {
    fragment.setUserVisibleHint(false);
}

如果您正在使用 FragmentStateAdapter,您应该使用 registerFragmentTransactionCallback 方法来检查 Fragment 与 ViewPager2 交互的生命周期。

我需要像我一样拥有 ViewPager2 的返回堆栈 ,实现是

init {
    // Add a FragmentTransactionCallback to handle changing
    // the primary navigation fragment
    registerFragmentTransactionCallback(object : FragmentTransactionCallback() {

        override fun onFragmentMaxLifecyclePreUpdated(
            fragment: Fragment,
            maxLifecycleState: Lifecycle.State
        ) = if (maxLifecycleState == Lifecycle.State.RESUMED) {

            // This fragment is becoming the active Fragment - set it to
            // the primary navigation fragment in the OnPostEventListener
            OnPostEventListener {
                fragment.parentFragmentManager.commitNow {
                    setPrimaryNavigationFragment(fragment)
                }
            }

        } else {
            super.onFragmentMaxLifecyclePreUpdated(fragment, maxLifecycleState)
        }
    })
}

我的问题是为 ViewPager2 的片段设置返回堆栈,每个片段只有在它们可见时才有自己的返回堆栈,因为在每个片段上设置 OnBackPressed 会导致不需要的弹出堆栈,您可以修改或使用 [=14= 的其他方法].

但是,我不知道它是否是误报,但 Leak Canary 有时会显示 FragmentMaxLifeCycleEnforcer 实例泄漏,所以如果您遇到这样的问题,您可能需要在 FragmentTransactionCallback 中注销 FragmentTransactionCallback onPause 或其他相关方法

片段本身有一个新方法

Return true if the fragment is in the resumed state. This is true for the duration of onResume() and onPause() as well.

package androidx.fragment.app;

final public boolean isResumed() {
   return mState >= RESUMED;
}

您可以通过键入以下内容调用此方法:

if (isResumed) {
    // your code here
}

不懂的简单解释一下

在你的 ViewPagerAdapter 中必须是这样的,构造函数发送 super

super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);

整个代码如下所示。

private static class ViewPagerAdapter extends FragmentPagerAdapter {

    private final List<Fragment> fragments = new ArrayList<>();
    private final List<String> fragmentTitle = new ArrayList<>();

    public ViewPagerAdapter(@NonNull FragmentManager fm) {
        super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
    }

    public void addFragment(Fragment fragment, String title) {
        fragments.add(fragment);
        fragmentTitle.add(title);
    }

    @NonNull
    @Override
    public Fragment getItem(int position) {
        return fragments.get(position);
    }

    @Override
    public int getCount() {
        return fragments.size();
    }

    @Nullable
    @Override
    public CharSequence getPageTitle(int position) {
        return fragmentTitle.get(position);
    }

}

这样,fragment中的onresume方法就可以了