ViewPager 默認 **銷毀離屏頁面** 以節省內存:
setOffscreenPageLimit(1) 默認值 → **只保留當前頁左右各 1 頁**。onDestroyView() 被調用 → View 被銷毀、數據清空。onCreateView() → 若未做緩存/恢復邏輯 → **空白/事件丟失**。| 方案 | 代碼 | 優點 | 缺點 |
|---|---|---|---|
| 增加緩存頁數(最簡單) | viewPager.setOffscreenPageLimit(3); | 一行代碼,Fragment 不銷毀,狀態完美保留 | 內存佔用線性增長,頁面多/重時慎用 |
| Fragment 內部懶加載 + 狀態保存 | 見下文 | 內存友好,生命周期規範 | 代碼量大,需正確處理 setUserVisibleHint/onHiddenChanged |
| ViewPager2 + FragmentStateAdapter | 遷移到 ViewPager2 | 官方推薦,默認行為更合理,支持 RecyclerView 難點復用 | 需遷移代碼,API 差異較大 |
public abstract class BaseLazyFragment extends Fragment {
private boolean isViewCreated = false;
private boolean isVisibleToUser = false;
private boolean isDataLoaded = false;
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
isViewCreated = true;
tryLoadData();
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
this.isVisibleToUser = isVisibleToUser;
tryLoadData();
}
private void tryLoadData() {
if (isViewCreated && isVisibleToUser && !isDataLoaded) {
loadData();
isDataLoaded = true;
}
}
// 子類實現具體加載邏輯
protected abstract void loadData();
@Override
public void onDestroyView() {
super.onDestroyView();
isViewCreated = false;
isDataLoaded = false; // 視業務決定是否重置
}
}
setOffscreenPageLimit **必須在設置 Adapter 之前調用** 生效。onCreateView 做耗時初始化**,放入 loadData() 或 onViewCreated。onViewCreated 會重新綁定。setUserVisibleHint,改用 FragmentTransaction.setMaxLifecycle(),遷移時注意。setOffscreenPageLimit(totalCount),最省事。setOffscreenPageLimit(1~2)。ViewPager 銷毀重建是設計使然,**要么加大緩存,要么做好懶加載與狀態恢復**,二選一,不可兼顧。