【原創】【ViewPager+Fragment】ViewPager中切換界面Fragment被銷毀的問題分析


ViewPager中切換界面Fragment被銷毀的問題分析

 

1、使用場景

ViewPager+Fragment實現界面切換,界面數量>=3
 

2、Fragment生命周期以及與Activity生命周期對比

                  

3、問題描述

按上圖所說,只有當Fragment所Attached的Activity執行destroy的時候才會調用onDestoryView方法,然而現實是:
當界面由2切換到1的時候,3界面對應的Fragment實際上走了如下流程:
1 -->onPause
2 -->onStop
3 -->onDestroyView

 

再由1切換回2或者3時,3界面對應的Fragment的執行流程:
1 -->onCreateView
2 -->onStart
3 -->onResume

 

可見,界面3對應的Fragment被銷毀並重新創建。

4、原因分析

ViewPager的默認加載方式是緩存當前界面前后相鄰的兩個界面,即最多共緩存包括當前界面在內的三個界面信息。當滑動切換界面的時候,非相鄰界面信息將被釋放。
界面2是當前界面,界面1和3是緩存界面,當切換到1時,界面2仍緩存,界面3被銷毀釋放,於是便有了onDestroyView的調用。
由1切換到2或3時,界面3又被重新創建,於是走了onCreateView流程。

5、解決方案

  • 方案一:設置ViewPager的緩存界面數
此方案適用於界面數較少的情況,避免緩存界面太多導致內存吃緊。
方法:
mPager .setOffscreenPageLimit(2);

參數:int limit    -    緩存當前界面每一側的界面數

以上述為例,當前界面為1,limit = 2,表示緩存2、3兩個界面。如此便避免了界面3被銷毀。
 
  • 方案二:保存狀態並恢復
此方案適用於可用界面信息可由狀態保存和恢復實現的情況。
在onDestroyView方法內保存相關信息,在onCreateView方法內恢復信息設置。
 
  • 方案三(推薦):復用Fragment的RootView
此方案適用通用場景,推薦使用。
步驟1:在onDestroyView方法內把Fragment的RootView從ViewPager中remove

1 @Override
2 public void onDestroyView() {
3     LogUtils.d(TAG , "-->onDestroyView");
4     super .onDestroyView();
5     if (null != FragmentView) {
6         ((ViewGroup) mFragmentView.getParent()).removeView(mFragmentView);
7     }
8 }

 

步驟2:在onCreateView方法內復用RootView
 1 @Override
 2 public View onCreateView(LayoutInflater inflater, ViewGroup container,
 3         Bundle savedInstanceState) {
 4     LogUtils.d (TAG, "-->onCreateView");
 5     if (null == mFragmentView) {
 6          mFragmentView = inflater.inflate(R.layout.fragment, container, false);
 7          mListView = (ListView) mFragmentView .findViewById(R.id.mm_listview);
 8          mListView.setAdapter(mAdapter);
 9          mPbar = (ProgressBar) mFragmentView.findViewById(R.id.pbar_mm_loading);
10          mPbar.setVisibility(View.VISIBLE);
11     }
12     
13     return mFragmentView ;
14 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM