标签:通过 文章 resume AC isa 适用于 show lan else
相信很多使用过 Fragment 的朋友都对判断 Fragment 是否对用户可见有此疑问,网上有很多文章也介绍得比较片面,只覆盖到了其中一种情况。我在项目中也有遇到这样的问题,经过试验和积累,已经总结出判断的方法并进行了封装,在这里给大家简单介绍下。
网上很多对这个方法的说明,这个方法只会在 ViewPager 和 FragmentPagerAdapter一起使用时才会触发。我们可以通过 getUserVisibleHint 来得到这个状态。
看下源码的说明:
/**
* Set a hint to the system about whether this fragment‘s UI is currently visible
* to the user. This hint defaults to true and is persistent across fragment instance
* state save and restore.
*
* <p>An app may set this to false to indicate that the fragment‘s UI is
* scrolled out of visibility or is otherwise not directly visible to the user.
* This may be used by the system to prioritize operations such as fragment lifecycle updates
* or loader ordering behavior.</p>
*
* <p><strong>Note:</strong> This method may be called outside of the fragment lifecycle.
* and thus has no ordering guarantees with regard to fragment lifecycle method calls.</p>
*
* @param isVisibleToUser true if this fragment‘s UI is currently visible to the user (default),
* false if it is not.
*/
public void setUserVisibleHint(boolean isVisibleToUser) {
if (!mUserVisibleHint && isVisibleToUser && mState < STARTED
&& mFragmentManager != null && isAdded()) {
mFragmentManager.performPendingDeferredStart(this);
}
mUserVisibleHint = isVisibleToUser;
mDeferStart = mState < STARTED && !isVisibleToUser;
}
/**
* @return The current value of the user-visible hint on this fragment.
* @see #setUserVisibleHint(boolean)
*/
public boolean getUserVisibleHint() {
return mUserVisibleHint;
}
上面说了,setUserVisibleHint 是在一定场景下才会使用的,单纯用 getUserVisibleHint 来判断可见是不对的。 这仅仅适用于 ViewPager 的情况。
onHiddenChanged 方法是在使用 show/hide 方法时会触发。来看下源码的说明:
/**
* Called when the hidden state (as returned by {@link #isHidden()} of
* the fragment has changed. Fragments start out not hidden; this will
* be called whenever the fragment changes state from that.
* @param hidden True if the fragment is now hidden, false otherwise.
*/
public void onHiddenChanged(boolean hidden) {
}
在我们使用show(fragment)和 hide(fragment)改变了 fragment 的显示状态时,会触发此函数,并且可以通过 isHidden() 来获取当前显示隐藏的状态。
我在 BaseFragment 中封装了onVisible();和onInvisible();两个回调,业务只需要覆写这两个方法就能根据 Fragment 可见状态的改变来写逻辑。
PS:这里说明一下,我封装的可见不可见回调,是在状态改变的时候回调的。如果已经是 hide 不可见了,再执行 onPause 方法时我就不会触发 onInvisible 的回调了,所以业务端可以根据回调进行逻辑处理。
直接看代码吧,代码中有详细的注释说明,这里就不多说了。
/**
* 当fragment与viewpager、FragmentPagerAdapter一起使用时,切换页面时会调用此方法
*
* @param isVisibleToUser 是否对用户可见
*/
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
boolean change = isVisibleToUser != getUserVisibleHint();
super.setUserVisibleHint(isVisibleToUser);
// 在viewpager中,创建fragment时就会调用这个方法,但这时还没有resume,为了避免重复调用visible和invisible,
// 只有当fragment状态是resumed并且初始化完毕后才进行visible和invisible的回调
if (isResumed() && change) {
if (getUserVisibleHint()) {
onVisible();
} else {
onInvisible();
}
}
}
/**
* 当使用show/hide方法时,会触发此回调
*
* @param hidden fragment是否被隐藏
*/
@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if (hidden) {
onInvisible();
} else {
onVisible();
}
}
@Override
public void onResume() {
super.onResume();
// onResume并不代表fragment可见
// 如果是在viewpager里,就需要判断getUserVisibleHint,不在viewpager时,getUserVisibleHint默认为true
// 如果是其它情况,就通过isHidden判断,因为show/hide时会改变isHidden的状态
// 所以,只有当fragment原来是可见状态时,进入onResume就回调onVisible
if (getUserVisibleHint() && !isHidden()) {
onVisible();
}
}
@Override
public void onPause() {
super.onPause();
// onPause时也需要判断,如果当前fragment在viewpager中不可见,就已经回调过了,onPause时也就不需要再次回调onInvisible了
// 所以,只有当fragment是可见状态时进入onPause才加调onInvisible
if (getUserVisibleHint() && !isHidden()) {
onInvisible();
}
}
还是用一些场景来说明一下吧。
关于 setUserVisibleHint 还是多说几句,代码中有判断 isResumed ,是因为在ViewPager中,一创建 Fragment 时就调用了 setUserVisibleHint 方法,此时回调可见不可见是不合适的,因为还没有把 View 创建好,所以增加了 isResumed 判断,因为在 onResume 时也会进行判断并且回调的,也避免了重复调用 onVisible 和 onInvisible。
判断 Fragment 对用户是否可见还是依赖于 getUserVisibleHint 和 isHidden 这两个重要方法的。这里也需要去理解 ViewPager 里 setUserVisibleHint 的作用,它只是把在屏幕外的 Fragment 加了一个标识,因为它也是被加到 window 中了,也是 onResume 状态了,所以用了一个新标识去表明不在屏幕内,标识为不可见。所以要结合判断,不能只判断其中一个。
标签:通过 文章 resume AC isa 适用于 show lan else
原文地址:https://www.cnblogs.com/ryq2014/p/9003951.html