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

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

I found that this part of the code is not executed.

How to solve:

They just changed API in Fragments.

If you use this method to limit fragments lifecycle:

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

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

If you need this method because you try to detect which fragment is currently visible in ViewPager. You can now just use onResume and onPause methods instead but before that you should change default behaviour in FragmentPagerAdapter constructor.

Like this:

FragmentPagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT)

###

Now in AndroidX method setUserVisibleHint(boolean isVisibleToUser) is deprecated and if you take a look into documentation, it says:

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.

So basically when you use this approach in FragmentTransaction:

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

would be equivalent to setUserVisibleHint(false) and:

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

would be equivalent to: setUserVisibleHint(true)

###

This answer assumes that you are using FragmentStatePagerAdapter

On the new version of androidx.fragment (from 1.1.0+), Fragment.setUserVisibleHint will still get called if your FragmentStatePagerAdapter is using the old behavior, specified by BEHAVIOR_SET_USER_VISIBLE_HINT.

If you have constructed your FragmentStatePagerAdapter and passed BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT, then Fragment.setUserVisibleHint will no longer be called inside FragmentStatePagerAdapter.instantiateItem.

NOTE: you can still call the deprecated Fragment.getUserVisibleHint if you have specified BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT in your FragmentStatePagerAdapter, but be advised that it will return true even though Fragment.isResumed() will return false.


The androidx project is open source. By taking a look at the latest code on master, you can see that an if has been added around setUserVisibleHint inside instantiateItem: 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);
}

Leave a Reply

Your email address will not be published. Required fields are marked *