最近公司的一個項目須要的Fragment可見的時候處理一些邏輯,UI結構並不是Tablayout+viewPager+Fragment結果,而是FragmentTabHost+Fragment的結構,因此有了一些坑,不知道你是否遇到過,從源碼層面看一下這些問題,寫出來但願你們判斷好與壞。bash
公司以前代碼是在onResume方法中寫邏輯,後來想了下,這明顯是不對的,你們都知道Fragment的onResume是依賴於附屬Activity的onResume方法的,當你從fragment的跳轉到另外一個Activity再次返回的時候,fragment附屬的Activity下的全部Fragment都會走onResume方法,咱們項目中onResume方法都是一些必須的網絡請求和一些與邏輯無關的操做,因此並未發現錯誤,在我動態適配狀態的過程發現了這個問題並研究了一下,下面來看這些方法!網絡
setUserVisibleHint方法,先看一下源碼:架構
public void setUserVisibleHint(boolean isVisibleToUser) {
if (!mUserVisibleHint && isVisibleToUser && mState < STARTED
&& mFragmentManager != null && isAdded()) {
mFragmentManager.performPendingDeferredStart(this);
}
mUserVisibleHint = isVisibleToUser;
mDeferStart = mState < STARTED && !isVisibleToUser;
}
複製代碼
咱們能夠看到,他只是Fragment源碼中的一個方法,這說明他是須要手動調用的,那爲何Fragment+ViewPager架構的能夠用這個方法來判斷Fragment是否可見呢?那麼就須要看一下Viewpager和與之結合的FragmentPagerAdapter源碼了,以下:ide
@Override
public Object instantiateItem(ViewGroup container, int position) {
...
if (fragment != mCurrentPrimaryItem) {
fragment.setMenuVisibility(false);
fragment.setUserVisibleHint(false);
}
return fragment;
}
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
Fragment fragment = (Fragment)object;
if (fragment != mCurrentPrimaryItem) {
if (mCurrentPrimaryItem != null) {
mCurrentPrimaryItem.setMenuVisibility(false);
mCurrentPrimaryItem.setUserVisibleHint(false);
}
if (fragment != null) {
fragment.setMenuVisibility(true);
fragment.setUserVisibleHint(true);
}
mCurrentPrimaryItem = fragment;
}
}
複製代碼
這個方法調用實際在FragmentPagerAdapter中。那麼當你是FragmentTabHost+Fragment的結構的時候,你會發現這個方法壓根不會被調用。ui
onHiddenChanged方法。源碼的註釋寫的很清楚了。this
/**
* Return true if the fragment has been hidden. By default fragments
* are shown. You can find out about changes to this state with
* {@link #onHiddenChanged}. Note that the hidden state is orthogonal
* to other states -- that is, to be visible to the user, a fragment
* must be both started and not hidden.
*/
若是該Fragment對象已經被隱藏,那麼它返回true。默認狀況下,Fragment是被顯示的。可以用onHiddenChanged(boolean)回調方法獲取該Fragment對象狀態的改變,要注意的是隱藏狀態與其餘狀態是正交的---也就是說,要把該Fragment對象顯示給用戶,Fragment對象必須是被啓動並不被隱藏。
#### 值得咱們注意的是
這裏的隱藏或者顯示是指Fragment調用show或者hider的時候纔會改變mHidden的值得
複製代碼
在FragmentTabHost+Fragment的結構的時候,當你跳轉到另外一個Activity再次返回的時候你會發現這方法並無走,由於當前Fragment並無改變show或者hide,故不會走。spa
isVisible方法code
若是使用這個方法判斷當前頁面是否隱藏了呢?我試了也是不行的,先看下這個方法的源碼:orm
final public boolean isVisible() {
return isAdded() && !isHidden() && mView != null
&& mView.getWindowToken() != null && mView.getVisibility() == View.VISIBLE;
}
複製代碼
若是你懂了onHiddenChanged方法,這應該就知道只使用它也是不行的,由於isHidden()的值和onHiddenChanged方法是有聯繫的。當你切換tab的時候,isVisible()放回是false。對象
趁此次需求,也詳細看了下這些生命週期的詳細理論,因此在FragmentTabHost+Fragment的結構的時候我是這樣解決的,以下:能適配第一次建立,tab切換,跳轉Activity再次返回多種狀況。
@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if (!hidden) {
onResumeCommon();
}
}
//isVisible() 重點是源碼中isHidden的值
//若是該Fragment對象已經被隱藏,也就是執行fragment執行hide()對象後,那麼它返回true。
@Override
public void onResume() {
super.onResume();
if (isVisible()) {
onResumeCommon();
}
}
private void onResumeCommon() {
StatusBarUtil.setStatusBarColor(mActivity, R.color.white);
StatusBarUtil.StatusBarLightMode(mActivity);
}
複製代碼
知識沒有學完了的一天,繼續努力!!!