相关文章推荐
礼貌的木瓜  ·  Package natbib Error: ...·  8 月前    · 
傲视众生的鞭炮  ·  SELTA SQUARE | IBM·  1 年前    · 
威武的大象  ·  start docker daemon ...·  1 年前    · 

在androidx.fragment.app.Fragment中,setUserVisibleHint()是Deprecated,并且没有执行,为什么?

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

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

android
androidx
limengxin
limengxin
发布于 2019-09-11
7 个回答
lukjar
lukjar
发布于 2022-08-12
已采纳
0 人赞同

他们只是在片段中改变了API。

如果你使用这种方法来限制碎片的生命周期。

你现在可以通过在FragmentTransaction上调用 setMaxLifecycle()来为一个FragmentTransaction设置最大生命周期状态。这取代了现在的 废弃的setUserVisibleHint()。

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

如果你需要这个方法,因为你试图在 ViewPager 中检测哪个片段是当前可见的。你现在可以直接使用 onResume onPause 方法,但在此之前你应该改变 FragmentPagerAdapter 构造函数中的默认行为。

Like this:

FragmentPagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT)
因为FragmentPagerAdapter也被弃用了,所以最好使用查看页面2现在。
在ViewPager2的情况下,这是默认行为,我们可以使用onResumeonPause的方法来知道当前哪个片段是可见的。

如果fragment不是ViewPager的一部分呢?我需要通知其他类片段在屏幕上出现或消失。有什么解决方案吗?
@LunaVulpo 有什么线索吗?
@Rajat Sangrame:在一个活动中,我有播放片段,在它们上面有控制片段和设置片段。我需要知道控制片断是否仍然可见,并在此基础上调整设置片断。用户体验要求。
@我可以用 FragmentStateAdapter 这种方式吗?
FragmentPagerAdapter也被废弃了。这简直是疯了,OMG GOOGLE。
Yupi
Yupi
发布于 2022-08-12
0 人赞同

现在,在 AndroidX 中,方法 setUserVisibleHint(boolean isVisibleToUser) 被废弃了,如果你看一下文档,它说。

你现在可以通过调用 Lifecycle 为一个片段设置一个最大的 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)

TheDerputy
TheDerputy
发布于 2022-08-12
0 人赞同

本答案假定你使用的是 FragmentStatePagerAdapter

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

如果你已经构建了你的 FragmentStatePagerAdapter 并通过了 BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT ,那么 Fragment.setUserVisibleHint 将不再在 FragmentStatePagerAdapter.instantiateItem 里面被调用。

NOTE: 如果你在你的 FragmentStatePagerAdapter 中指定了 BEHAVIOR_SET_USER_VISIBLE_HINT ,你仍然可以调用废弃的 Fragment.getUserVisibleHint ,但是要注意它将返回 true ,尽管 Fragment.isResumed() 将返回false。

androidx 项目是开源的。通过查看master上的最新代码,你可以看到在 setUserVisibleHint 周围的 instantiateItem 中已经添加了一个 if https://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);
        
    prsnlme
    prsnlme
    发布于 2022-08-12
    0 人赞同

    在片段本身有一个新的方法

    如果该片段处于恢复状态,则返回true。在onResume()和onPause()的持续时间内,这也是真的。

    package androidx.fragment.app;

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

    你可以通过键入来调用这个方法。

    if (isResumed) {
        // your code here
        
    与FragmentStatePager配合良好
    Nirva
    Nirva
    发布于 2022-08-12
    0 人赞同

    为那些不理解的人做一个简单的解释。

    在你的ViewPagerAdapter中必须像这样,构造器发送超级

    super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
    

    The whole code looks like this.

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

    这样一来,片段中的onresume方法就会发挥作用。

    Thracian
    Thracian
    发布于 2022-08-12
    0 人赞同

    如果你正在使用 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会导致不想要的弹出栈,你可以修改或使用FragmentTransactionCallback的其他方法。

    然而,我不知道这是否是误报,但Leak Canary显示FragmentMaxLifeCycleEnforcer实例有时会泄漏,所以如果你面临这样的问题,你可能需要在onPause中取消注册FragmentTransactionCallback或其他相关方法。

    sandip
    sandip
    发布于 2022-08-12
    0 人赞同

    我在kotlin中使用下面的代码来处理当一个片段对用户可见时的代码。

    Class ZeroFragment : Fragment() {
    //Below onResume executed when this fragment is displayed to the user.
        override fun onResume() {