【问题标题】:in androidx.fragment.app.Fragment,setUserVisibleHint()is Deprecated,and not executed,why?在androidx.fragment.app.Fragment中,setUserVisibleHint()被Deprecated,并且没有被执行,为什么?
【发布时间】:2019-09-11 09:15:23
【问题描述】:
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (getUserVisibleHint()) {
        isVisible = true;
        onVisible();
    } else {
        isVisible = false;
        onInVisible();
    }
}

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

【问题讨论】:

    标签: android androidx


    【解决方案1】:

    他们只是在 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)
    

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

    【讨论】:

    • 如果片段不是 ViewPager 的一部分怎么办?我需要通知其他类片段显示或消失在屏幕上。有什么解决办法吗?
    • @LunaVulpo 任何线索?
    • @Rajat Sangrame:在一项活动中,我有播放片段,并通过它们控制片段和设置片段。我需要知道控件片段是否仍然可见并基于该调整设置片段。用户体验要求。
    • @我可以用FragmentStateAdapter这个方法吗?
    • FragmentPagerAdapter 也被弃用了。太疯狂了,天哪,GOOGLE。
    【解决方案2】:

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

    您现在可以通过调用为 Fragment 设置最大 Lifecycle 状态 setMaxLifecycle()FragmentTransaction 上。这取代了现在 已弃用 setUserVisibleHint()FragmentPagerAdapterFragmentStatePagerAdapter 有一个新的构造函数,允许你 切换到新的行为。

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

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

    相当于setUserVisibleHint(false) 和:

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

    相当于:setUserVisibleHint(true)

    【讨论】:

      【解决方案3】:

      此答案假设您使用的是FragmentStatePagerAdapter

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

      如果你已经构建了你的FragmentStatePagerAdapter 并传递了BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT,那么Fragment.setUserVisibleHint 将不再在FragmentStatePagerAdapter.instantiateItem 中被调用。

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


      androidx 项目是开源的。通过查看master上最新的代码,可以看到setUserVisibleHintinstantiateItem里面添加了一个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);
      }
      

      【讨论】:

        【解决方案4】:

        如果你使用FragmentStateAdapter,你应该使用registerFragmentTransactionCallback方法来检查片段与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 实例泄漏,所以如果您遇到这样的问题,您可能需要在 onPause 或其他相关人员中取消注册 FragmentTransactionCallback方法

        【讨论】:

          【解决方案5】:

          片段本身有一个新方法

          如果片段处于恢复状态,则返回 true。在 onResume() 和 onPause() 期间也是如此。

          package androidx.fragment.app;

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

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

          if (isResumed) {
              // your code here
          }
          

          【讨论】:

          • 与 FragmentStatePager 配合得很好
          【解决方案6】:

          给不懂的人简单解释一下。

          在你的 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方法就可以工作了。

          【讨论】:

            猜你喜欢
            • 2012-12-25
            • 1970-01-01
            • 2021-09-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-03-24
            • 1970-01-01
            相关资源
            最近更新 更多