6

爲了專注於問題,我會的情況下簡化爲以下 - 我有一個活動和片段F正在添加另一個片段。每個簡化代碼異常[片段不再存在鍵機器人:target_state]

活動A

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    // do some stuff 
    FragmentManager fm = getSupportFragmentManager(); 
    F f = new F(); 
    fm.beginTransaction() 
      .add(R.id.content, f) 
      .commit(); 
} 

片f

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    // do some stuff 
    FragmentManager fm = getChildFragmentManager(); 
    FragmentTransaction transaction = fm.beginTransaction(); 
    ChildFragment childFragment = new ChildFragment(); 
    childFragment.setTargetFragment(this, 1); 
    transaction.add(R.id.f, childFragment); 
    transaction.commit(); 

    return view; 
} 

子片段的代碼是不相關的問題,所以我不會發布它。

使用此代碼一切似乎都正常工作,直到我綜合火力地堡,並開始得到以下故障報告

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.test.test/com.test.test.A}: java.lang.IllegalStateException: Fragment no longer exists for key android:target_state: index 1 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2377) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2429) 
    at android.app.ActivityThread.access$800(ActivityThread.java:151) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1342) 
    at android.os.Handler.dispatchMessage(Handler.java:110) 
    at android.os.Looper.loop(Looper.java:193) 
    at android.app.ActivityThread.main(ActivityThread.java:5341) 
    at java.lang.reflect.Method.invokeNative(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:515) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:825) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:641) 
    at dalvik.system.NativeStart.main(Native Method) 

起初我無法重現的異常,但測試了一段時間後,我發現,如果開發人員選項不要讓活動在其上發生幾乎每次我將活動帶到後臺並恢復它。我認爲在正常情況下,當活動放在後臺並且應用程序被破壞時會發生。

經過一番研究後,我得出結論,崩潰的真正原因是F片段被設置爲它的孩子的目標片段。我可以確認,如果我不設置目標片段,崩潰不會發生。

我不是很確定,但似乎崩潰的原因是子片段及其目標片段位於不同的片段管理器中。所以我嘗試的第一件事就是將所有片段放在活動的片段管理器中。

片f

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    // do some stuff 
    // I do not want to use private fragment manager but rather use the activity's 
    // FragmentManager fm = getChildFragmentManager(); 
    FragmentManager fm = getFragmentManager(); 
    // do the other stuff 
} 

這解決了這個問題。但導致另一個。當我從活動中刪除片段(我想用另一個片段替換它)。子片段無法保存其狀態,因爲它具有對從管理器中刪除的其父片段的引用。

Process: com.test.test, PID: 11047 java.lang.IllegalStateException: Failure saving state: ChildFragment{423c10f0 #1 id=0x7f0b0058} has target not in fragment manager: F{423c0f88} 
    at android.support.v4.app.FragmentManagerImpl.saveAllState(FragmentManager.java:2618) 
    at android.support.v4.app.FragmentController.saveAllState(FragmentController.java:134) 
    at android.support.v4.app.FragmentActivity.onSaveInstanceState(FragmentActivity.java:571) 
    at android.support.v7.app.AppCompatActivity.onSaveInstanceState(AppCompatActivity.java:515) 
    at android.app.Activity.performSaveInstanceState(Activity.java:1157) 
    at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1229) 

我可以嘗試更深入和刪除的子片段時,其父被刪除,但我有一種感覺,這是不是這樣做的正確方法,畢竟我認爲正確的方法做,這是使用getChildFragmentManager()。

任何有關該主題的幫助,建議,指導方針將非常感激。

+0

爲什麼不創建和添加碎片只能從一個地方 - 活動A? – helleye

+0

它會使片段不可重用。所有添加片段的活動也必須添加子片段。 –

+0

您是否嘗試過https://code.google.com/p/android/issues/detail?id=54520 – Krish

回答

3

我已經改變了這樣的代碼,它是爲我工作, 更改ActivityA這樣,

@Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity); 

     FragmentManager fm = getSupportFragmentManager(); 
     if (fm.findFragmentById(R.id.content) == null) { 
      F f = new F(); 
      fm.beginTransaction() 
        .add(R.id.content, f) 
        .commit(); 
     } 
    } 

而且你可以用你以前的實現像setTargetFragment爲ChildFragment片段。這解決了你在問題中提到的第一個例外。

+0

@MojoRisin你有沒有試過我的答案? – Krish

+0

看來我在錯誤的地方尋找解決方案。正如你指出的那樣,問題在於我添加了片段,無論它是否已經存在。 –