前幾天做項目的時候用到了viewpager嵌套fragment,以前都是用的第三方的,沒有出現過問題,前幾天做的時候發現,在fragmentA加載資料的時候,加載框一直轉,等到fragmentA加載資料完成,還在轉,一直不明白為什麼,原以為是封裝的加載框出問題了,偶然間發現是因為後邊兩個fragmentB和fragmentC沒有加載完資料,是以加載框一直旋轉個不停,沒辦法,先去掉加載框,就那麼運作了。
今天正好有時間,研究下哪裡出的問題,發現原來是viewpager的問題,viewpager有預加載的功能,如果不明白的可以看我之前發過的一篇博文,
連接配接http://blog.csdn.net/sinat_29874521/article/details/52869253
好了,言歸正傳,感謝http://www.cnblogs.com/wangfeng520/p/5807465.html提供的幫助,裡邊說的很詳細,用的方法也很好
源碼
/**
* 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>
*
* @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.performPendingDeferredStart(this);
}
mUserVisibleHint = isVisibleToUser;
mDeferStart = !isVisibleToUser;
}
需要注意的是這個方法會在Fragment的onCreate()方法調用之前就調用
/**
* @return The current value of the user-visible hint on this fragment.
* @see #setUserVisibleHint(boolean)
*/
public boolean getUserVisibleHint() {
return mUserVisibleHint;
}
原諒我英語不好,我就不翻譯了,說白了就是一句話
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
}
這裡isVisibleToUser,就是判斷該fragment是否是使用者可見的視圖,如果是則為true,不是則是false。而getUserVisibieHint()則是用來擷取狀态資訊的,可見是true,不可見是false
用法當然更簡單了
當然,還需要看一個方法的源碼
/**
* Return true if the fragment is currently visible to the user. This means
* it: (1) has been added, (2) has its view attached to the window, and
* (3) is not hidden.
*/
final public boolean isVisible() {
return isAdded() && !isHidden() && mView != null
&& mView.getWindowToken() != null && mView.getVisibility() == View.VISIBLE;
}
用來做判斷的,很容易了解,isVisible()方法可以判斷Fragment的視圖是否建立好,對于第一個顯示的Fragment,因為isVisibleToUSer是true,但是isVisible()是false,那麼在顯示第一個Fragment的時候是空白的。但是對于其它的Fragment,因為存在ViewPager的預加載,當顯示到Fragment的時候,isVisible()是true,而不是false。是以會在這個方法裡面進行加載資料的操作
好了說下用法
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser && isVisible()){
setDatas();//擷取資料
}
}
雙重判斷,省的做其他邏輯處理
@Override
public void onResume() {
super.onResume();
if(getUserVisibleHint()){
isFresh = true;
setDatas();
}
}
因為我的擷取資料的方法是重新整理和加載全部解除安裝一起了是以isFresh = true可以忽略,之是以我這麼寫,不會重複加載資料,是因為我在擷取初始化資料的時候,清空了資料集合,當然,這麼做處于使用者考慮,肯定不合理,畢竟費流量啊,不過其他的不考慮了,後續修改
PS:為何setUserVisibleHint()明明在onCreate()之前執行,但是還可以在裡邊寫擷取加載資料的方法呢?原因很簡單,就是因為viewpager有預加載的功能,是以在進入這個fragment之前,viewpager就把這個fragment的控件加載完成了,而因為這個fragment是不可見的,是以isVisible()方法就是false,而不會運作加載資料的方法,但是說明一下,setUserVisibleHint()不是随着fragment的生命周期運作的,而是需要手動調用的,自己運作一下debug就明白了,回歸正題,因為viewpager已經加載完成了所有控件,是以在運作到該fragment,該fragment可見,那麼運作setUserVisibleHint(),而此時控件已經被viewpager預加載完成,isVisible()則是true,是以就可以吧加載資料的方法下載下傳裡邊了。
反正我是這麼了解的,如果有不對的地方請指出來,謝謝!