首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android Fragment 事務管理:replace 替代 add 解決重複添加崩潰

     編輯:程式設計綜合問答

錯誤:`IllegalStateException: Fragment already added: LeagueFragment`,Tab 切換時反覆 `add` 同一 Fragment 實例導致崩潰。

問題代碼分析

// ❌ 每次切換都嘗試 add,若已 added 崩潰
if (!fragment.isAdded()) {
    transaction.add(R.id.container, fragment, tag);
}
// 隱藏其他
for (int i = 0; i < 4; i++) if (i != pos) transaction.hide(fragments[i]);
transaction.show(fragment).commit();

核心修正:`replace` + `show/hide` 混合模式

private void switchTab(int position) {
    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    Fragment target = fragments[position];
    
    // 1. 隱藏所有已添加的 Fragment
    for (Fragment f : fragments) {
        if (f != null && f.isAdded()) ft.hide(f);
    }
    
    // 2. 目標 Fragment:未添加則 add,已添加則 show
    if (!target.isAdded()) {
        ft.add(R.id.container, target, String.valueOf(position));
    } else {
        ft.show(target);
    }
    
    ft.commit();
}

更優方案:ViewPager2 + FragmentStateAdapter (現代標準)

// 1. 布局
<androidx.viewpager2.widget.ViewPager2
    android:id="@+id/viewPager"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

// 2. 適配器
class TabAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa) {
    private val fragments = listOf(MshopFragment(), ApplyFragment(), LeagueFragment(), MyFragment())
    override fun getItemCount() = fragments.size
    override fun createFragment(position: Int) = fragments[position]
}

// 3. 綁定 TabLayout
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
    tab.text = titles[position]
    tab.icon = icons[position]
}.attach()

// 4. 預加載鄰頁(可選)
viewPager.offscreenPageLimit = 1

遷移優勢對比

指標手動 FragmentTransactionViewPager2 + FSA
代碼量~80 行~20 行
生命周期管理手動 hide/show自動 DESTROY/CREATE
滑動手勢需自行實現原生支援
預加載控制無`offscreenPageLimit`
動畫定制困難`FragmentTransaction` 兼容

避坑指南

  • ❌ 不要在 `onCreateView` 執行耗時操作,移至 `onViewCreated` 或 `onStart`。
  • ❌ 不要持有 `Context`/`View` 引用跨越 Fragment 生命周期,用 `requireContext()`/`requireView()` 現用現取。
  • ✅ `FragmentStateAdapter` 會自動銷毀離屏 Fragment,重建時調用 `onSaveInstanceState` 保存狀態。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved