1. 程式人生 > >ViewPager+ Fragment結合的setUserVisibleHint()呼叫時機

ViewPager+ Fragment結合的setUserVisibleHint()呼叫時機

    最近的專案使用到了ViewPager + Fragment的模式,要求在每次Fragment獲取顯示的時候來重新整理資料,該專案下ViewPager有5個子fragment,在onCreateView及fragment的setUserVisibleHint(bool isVisibleToUser)中的isVisibleToUser為true的時候重新整理資料的時候出現數據多次重新整理的情況,因此對ViewPage + Fragment的生命週期做了研究。

    專案佈局最頂層5個button,主體是ViewPager+fragment, 可以通過點選button直接跳轉到對應的fragment,也可以通過左右滑動來進行相鄰跳轉。


為了研究多個fragment的生命週期,加入列印如下:

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        Slog.i("onCreateView 3");
        View view = inflater.inflate(R.layout.my_police_events_fragment, container, false);
        return view;
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        Slog.i("setUserVisibleHint 3 " + isVisibleToUser);
        super.setUserVisibleHint(isVisibleToUser);
    }

    @Override
    public void onDestroyView() {
        Slog.i("onDestroyView 3 ");
        super.onDestroyView();
    }

1. 第一次進入該activity,fragment1被選中,列印如下:

第一次進入
setUserVisibleHint 1 false
setUserVisibleHint 2 false
setUserVisibleHint 1 true
onCreateView 1
onCreateView 2

 建立了fragment1和fragment2, 且fragment1中的setUserVisibleHint引數為true

2. 從fragment1切換到fragment2,fragment2被選中,列印如下:

從1--->2
setUserVisibleHint 3 false
setUserVisibleHint 1 false
setUserVisibleHint 2 true
onCreateView 3

   建立了fragment3,且fragment2中的setUserVisibleHint引數為true

3.從fragment2切換到fragment3,fragment3被選中,列印如下:

從2--->3
setUserVisibleHint 4 false
setUserVisibleHint 2 false
setUserVisibleHint 3 true
onDestroyView 1 
onCreateView 4

 建立了fragment4,銷燬了fragment1,且fragment3中的setUserVisibleHint引數為true

4. 後面滑動的過程日誌列印如下:

從3--->2
setUserVisibleHint 1 false
setUserVisibleHint 3 false
setUserVisibleHint 2 true
onCreateView 1
onDestroyView 4

從2--->3
setUserVisibleHint 4 false
setUserVisibleHint 2 false
setUserVisibleHint 3 true
onDestroyView 1 
onCreateView 4

從3--->4
setUserVisibleHint 5 false
setUserVisibleHint 3 false
setUserVisibleHint 4 true
onDestroyView 2
onCreateView 5

從4--->5
setUserVisibleHint 4 false
setUserVisibleHint 5 true
onDestroyView 3 

猜測:通過以上日誌,可以發現,不論fragment如何變化,首先被選中的fragment會呼叫引數為true的setUserVisibleHint方法,被選中的fragment與相鄰的fragment的狀態肯定是onCreate的狀態(如果未create就呼叫onCreateView,如果已經是onCreate的狀態不呼叫),相鄰的fragment會呼叫引數為false的setUserVisibleHint方法,其他的fragment是處於onDestroy的狀態。

5. 為了驗證我們的猜想,將不再採用相鄰滑動的方式,採用button點選跳轉的方式來檢驗fragment的生命週期。相關列印如下:

從5--->2
setUserVisibleHint 2 false
setUserVisibleHint 1 false
setUserVisibleHint 3 false
setUserVisibleHint 5 false
setUserVisibleHint 2 true
onCreateView 2
onCreateView 1
onCreateView 3
onDestroyView 4 
onDestroyView 5 

從2--->4
setUserVisibleHint 4 false
setUserVisibleHint 5 false
setUserVisibleHint 2 false
setUserVisibleHint 4 true
onCreateView 4
onCreateView 5
onDestroyView 2 
onDestroyView 1 

總結:可以看到,不管fragment如何變化,都是按照上面的規則進行變動的,知道了fragment的生命週期,那麼就可以選擇在合適的時期對我們的資料進行處理了,避免出現數據未載入或者多次載入的情況了。

Google預載入相鄰的fragment是為了滑動更加流暢,給使用者更佳的體驗感。