需求
在操作ViewPager時(shí),需要知道Fragment對用戶展示、隱藏的時(shí)刻。
背景
因?yàn)?code>ViewPager通過 setOffscreenPageLimit提供預(yù)加載的功能,所以傳統(tǒng)生命周期的onResume()、onPause()不能準(zhǔn)確的表達(dá)Fragment對用戶是否可見。
傳統(tǒng)的做法是給ViewPager的onPageSelect()事件里,發(fā)送一個(gè)廣播,通知Fragment當(dāng)前頁發(fā)生了變化。Fragment對比自身position和廣播攜帶的參數(shù)position是否一致,判斷自己是否當(dāng)前頁,以此來執(zhí)行 展示、隱藏操作。
優(yōu)化
Fragment的生命周期里,提供了一個(gè)setUserVisibleHint(boolean isVisibleToUser)函數(shù)。它的作用是告訴系統(tǒng)Fragment是否對用戶可見,使用場景是在ViewPager的適配器FragmentStatePagerAdapter和FragmentStatePagerAdapter
我們看下引用這個(gè)函數(shù)的地方
- 實(shí)例化Fragment
@Override
public Object instantiateItem(ViewGroup container, int position) {
//....創(chuàng)建Fragment操作....
if (fragment != mCurrentPrimaryItem) {
//....其他操作....
//不是當(dāng)前頁,則設(shè)置hint為flase
fragment.setUserVisibleHint(false);
}
return fragment;
}
- 設(shè)置Fragment為當(dāng)前項(xiàng)
public void setPrimaryItem(ViewGroup container, int position, Object object) {
Fragment fragment = (Fragment)object;
if (fragment != mCurrentPrimaryItem) {
if (mCurrentPrimaryItem != null) {
//....其他操作....
//老的設(shè)置為不可見
mCurrentPrimaryItem.setUserVisibleHint(false);
}
if (fragment != null) {
//....其他操作....
//新的設(shè)置為可見
fragment.setUserVisibleHint(true);
}
mCurrentPrimaryItem = fragment;
}
}
需要注意的是,setUserVisibleHint()和Fragment的生命周期是沒關(guān)聯(lián)的的。

setUserVisibleHint,在ViewPager左右滑動(dòng)的時(shí)候,因?yàn)轭A(yù)加載的機(jī)制,所以頁面已經(jīng)初始化好;
但是通過setCurrentItem(頁碼);跳到某個(gè)頁面時(shí),此時(shí)頁面還未初始化。
我們業(yè)務(wù)里面的操作,需要頁面布局已經(jīng)完成,因此在使用它的時(shí)候,我們需要額外的技巧,下面修改后的XLBaseFragment
子類重寫 showToUserInViewPager和hideToUserInViewPager()即可
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
//狀態(tài)如果一致,則不去做操作
if (mIsShowToUser == isVisibleToUser) return;
//從隱藏切到顯示
if (isVisibleToUser) {
if (mIsViewInitial) {
showToUserInViewPager();
mRemainShowEventToTake = false;
} else {
mRemainShowEventToTake = true;
}
} else {
//從顯示切到隱藏
hideToUserInViewPager();
}
mIsShowToUser = isVisibleToUser;
}
@Override
public final View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//一些操作。。
if (mRemainShowEventToTake && getUserVisibleHint()) {
mRemainShowEventToTake = false;
showToUserInViewPager();
}
}