在androidx.fragment.app.Fragment中,不赞成使用setUserVisibleHint(),为什么不执行?

时间:2019-09-11 09:15:23

标签: android androidx

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

我发现这部分代码没有执行。

4 个答案:

答案 0 :(得分:16)

他们只是更改了Fragments中的API。

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

  

您现在可以通过调用设置片段的最大生命周期状态   FragmentTransaction上的setMaxLifecycle()。这取代了现在   不推荐使用setUserVisibleHint()。

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

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

像这样:

FragmentPagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT)

答案 1 :(得分:9)

此答案假定您使用的是FragmentStatePagerAdapter

在新版本的androidx.fragment(从1.1.0+版本开始)中,如果您的Fragment.setUserVisibleHint使用的是由FragmentStatePagerAdapter指定的旧行为,则BEHAVIOR_SET_USER_VISIBLE_HINT仍会被调用

如果您构造了FragmentStatePagerAdapter并通过了BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT,则Fragment.setUserVisibleHint将不再在FragmentStatePagerAdapter.instantiateItem内部被调用。

注意::如果您在Fragment.getUserVisibleHint中指定了BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT,仍然可以调用已弃用的FragmentStatePagerAdapter,但建议它返回{{1 }},即使true返回false。


Fragment.isResumed()项目是开源的。通过查看master上的最新代码,您可以看到在androidxhttps://android.googlesource.com/platform/frameworks/support/+/androidx-master-dev/fragment/fragment/src/main/java/androidx/fragment/app/FragmentStatePagerAdapter.java#195

if周围添加了setUserVisibleHint

TL; DR:

1.0.x:

instantiateItem

1.1.0 +:

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

答案 2 :(得分:4)

现在不建议使用AndroidX方法setUserVisibleHint(boolean isVisibleToUser)中的方法,如果您查看文档,它会显示:

  

您现在可以通过调用来设置片段的最大Lifecycle状态   setMaxLifecycle()上的FragmentTransaction。这取代了现在   不推荐使用的setUserVisibleHint()FragmentPagerAdapter和   FragmentStatePagerAdapter有一个新的构造函数,可让您   切换到新行为。

基本上,当您在FragmentTransaction中使用这种方法时:

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

等同于setUserVisibleHint(false)并且:

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

等同于:setUserVisibleHint(true)

答案 3 :(得分:0)

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

我需要将ViewPager2作为i asked here的后栈,实现是

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会导致不希望的弹出堆栈,您可以修改或使用FragmentTransactionCallback的其他方法。

但是,我不知道它是否为假阳性,但Leak Canary有时显示FragmentMaxLifeCycleEnforcer实例泄漏,因此,如果您遇到这样的问题,则可能需要在{{ 1}}或其他相关方法