2015-09-28 35 views
1

我的Activity中有一個偵聽器,在另一個線程完成網絡請求後,替換一個Fragment。因此,這偵聽器調用的代碼行是這樣的:何時使用FragmentManager.isDestroyed()?避免IllegalStateException?

getFragmentManager().beginTransaction().replace(R.id.container, fragment, fragmentTag).commit(); 

的提交()在這行代碼偶爾拋出IllegalStateException。根據the docs

事務只能在其包含活動保存其狀態之前使用此方法提交。如果在該點之後嘗試提交,則會拋出異常。這是因爲如果活動需要從其狀態恢復,則提交後的狀態可能會丟失。有關可能會丟失提交的情況,請參閱commitAllowingStateLoss()。

雖然看着這個,我碰到了FragmentManager.isDestroyed()方法。 javadoc閱讀:

如果最終的Activity.onDestroy()調用已在FragmentManager的Activity上進行,則返回true,所以此實例現在已經死亡。

我想我只是對FragmentManager的Activity實例的影響感到困惑。什麼時候應該使用FragmentManager.isDestroyed()?在提交替換FragmentTransaction之前檢查它是否會避免IllegalStateException?

+0

你應該張貼您的logcat錯誤 –

+0

我一直在經歷着同樣的事情......我發現,這是完全正確的:在我所有的情況下,FragmentManager.isDestroyed()返回true,則FragmentTransaction.commit( )會拋出IllegalStateException。事實上,首先檢查.isDestroyed()將幫助您避免異常,但是您也不會執行Fragment事務。 – alpartis

+0

@alpartis我會添加一些更好的日誌記錄,並查看當我得到IllegalStateException時FragmentManager.isDestroyed()返回true。儘管您的評論似乎足以成爲答案。如果你把它作爲一個發佈,而沒有人在一段時間內發佈更好的,我會接受它。 – pumpkinpie65

回答

1

我的代碼如下所示。當執行時,事情要麼正常工作,要麼顯示我想要的片段,要麼收到指示.isDestroyed()爲真的日誌消息。如果我刪除.isDestroyed()的檢查,那麼ft.commit()將拋出IllegalStateException。

該解決方案可防止產生的崩潰,但它不一定能解決爲什麼它首先出現的底層時序問題。

import android.support.v4.app.Fragment; 
import android.support.v4.app.FragmentManager; 
import android.support.v4.app.FragementTransaction; 

public class CallingCard extends Fragment 
{ 
    // ... some stuff for my fragment ... 
} 

public class MyFragment extends Fragment 
{ 
    public void showCallingCard() { 
     CallingCard callingCard = new CallingCard(); 
     FragmentManager fm = parent.getSupportFragmentManager(); 

     // ensure serialization of fragment transactions 
     fm.executePendingTransactions(); 

     if (!fm.isDestroyed()) { 
      // attempt to display fragment 
      FragementTransaction ft = fm.beginTransaction(); 
      ft.replace(R.id.fragPlaceHolder, callingCard); 
      ft.commit(); 
     } else { 
      Log.e("tag", "fm.isDestroyed() was true"); 
     } 
    } 
} 
+0

在我的情況下,Fragments沒有被正確/完全清理,但他們的'.Destroy()'等方法已被調用。隨後,當我的片段第二次出現時,內部狀態變量全部沒有了(這是一個技術術語),我的片段事務將失敗,因爲Android仍然認爲包含的片段仍然被銷燬(如' .isDestroyed()')。 – alpartis

+0

開始從我的日誌中獲取一些數據,我仍然收到崩潰,它看起來像'fm.isDestroyed()'返回'false'。 – pumpkinpie65

+0

Android在所有情況下都不一定會處理片段事務。在某些情況下,爲確保正確的序列化,您需要採取一些強力措施。在開始新的事務之前,向'.executePendingTransactions()'添加一個調用。我會嘗試更新我的答案,以反映這一點。 – alpartis

0

保持一個標誌來知道活動的當前狀態。檢查onPause狀態。

在活動進入onPause狀態後,不要進行片段管理器事務。這爲我工作.. !!!

@Override 
protected void onPause() { 
    super.onPause(); 
    isPaused = true; 

} 

@Override 
protected void onResume() { 
    super.onResume(); 
    isPaused = false; 
} 

//檢查isPaused標誌。

​​