首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

Android Fragment + ViewPager 優化:緩存 View 避免重複加載

     編輯:關於C++

問題現象

使用 `Fragment + ViewPager` 時,滑動切換頁面會觸發 `onDestroyView` -> `onCreateView` 重建,導致佈局重新加載、數據重複請求,造成卡頓和流量浪費。默認 `ViewPager` 只緩存當前頁及相鄰頁,第三頁的 View 會被銷毀。

生命周期驗證

實驗 4 個 Fragment,滑動日誌顯示:

  • 進入第 1 頁:創建 1、2
  • 滑到第 2 頁:創建 3
  • 滑到第 3 頁:銷毀 1 的 View,創建 4
  • 滑回第 2 頁:重新 `onCreateView` 2

結論:`onCreateView` 多次調用,`onCreate` 僅調用一次。

優化方案:基類緩存 RootView

public abstract class BaseFragment extends Fragment {
    private View rootView;
    protected Context context;
    private boolean hasInitData = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        context = getActivity();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        if (rootView == null) {
            rootView = initView(inflater); // 子類實現佈局加載
        }
        // 關鍵:從父容器移除,防止 "already has parent" 崩潰
        ViewGroup parent = (ViewGroup) rootView.getParent();
        if (parent != null) parent.removeView(rootView);
        return rootView;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if (!hasInitData) {
            initData(); // 子類實現數據加載,僅執行一次
            hasInitData = true;
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        // 不再需要手動 removeView,onCreateView 會處理
        // 但若需釋放圖片等資源可在這裡處理
    }

    protected abstract View initView(LayoutInflater inflater);
    protected abstract void initData();
    
    // 封裝網絡請求...
}

核心要點

  1. 緩存 `rootView`: 避免重複 `inflate` 佈局。
  2. 標記 `hasInitData`: 確保 `initData()`(含網絡請求)僅執行一次。
  3. 移除父 View: `onCreateView` 返回前必須 `parent.removeView(rootView)`,否則二次添加會拋異常。
  4. 不銷毀數據: `onDestroyView` 不重置 `hasInitData`,保持數據不重載。

適用場景

  • 頁面數較少(≤5),數據不需實時刷新的場景。
  • 若頁面多或需實時數據,建議配合 `setOffscreenPageLimit` 或使用 `RecyclerView` 替代。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved