2013-10-18 12 views
9

Ho un problema con un'app Android compilata e in esecuzione con SDK target 4.3. L'app ha due attività, una attività principale che è anche l'attività di avvio e una seconda attività. Entrambi stanno usando Frammenti. Per supportare anche dispositivi più vecchi, viene utilizzata la lib di supporto.java.lang.IllegalStateException: Frammento già aggiunto

Nel seguente scenario si tratta dell'errore "IllegalStateException: frammento già aggiunto".

1) Avviare l'applicazione -> MainActivity è mostrata
2) passare alla SecondActivity con intento
3) Premere il Tasto Home
4) Attendere un tempo più lungo (testato con 24 ore)
5) premere nuovamente l'icona dell'app -> Eccezione. Se il tempo è più breve, la SecondActivity viene mostrata come previsto.

Ho letto un sacco di IllegalStateExceptions durante la gestione dei frammenti, ma tutti loro hanno indicato un problema con un metodo replace(). In Stacktrace, il mio codice non viene mai chiamato.

Il Fragement viene aggiunto nel Activies onCreate() Metodo:

protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(..); 
    ListFragment listFragment = this.getCaptureListFragment(); 
    FragmentTransaction tx = this.getSupportFragmentManager().beginTransaction(); 
    tx.add(R.id.MainFragmentContainer, listFragment, "list_fragment_tag"); 
    tx.commit(); 
} 

private ListFragment getListFragment() { 
    ListFragment listFragment = (ListFragment) this.getSupportFragmentManager().findFragmentByTag("list_fragment_tag"); 
    if (listFragment == null) { 
     listFragment = new ListFragment(); 
    } 
    return listFragment; 
} 


java.lang.RuntimeException: Unable to start activity ComponentInfo{de.myexample.demo/de.myexample.demo.ui.SecondActivity}: java.lang.IllegalStateException: Fragment already added: ListFragment{42283f58 #0 id=0x7f060094 de.myexample.demo.ui.ListFragment} 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2211) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261) 
    at android.app.ActivityThread.access$600(ActivityThread.java:141) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256) 
    at android.os.Handler.dispatchMessage(Handler.java:99) 
    at android.os.Looper.loop(Looper.java:137) 
    at android.app.ActivityThread.main(ActivityThread.java:5103) 
    at java.lang.reflect.Method.invokeNative(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:525) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 
    at dalvik.system.NativeStart.main(Native Method) 
Caused by: java.lang.IllegalStateException: Fragment already added: ListFragment{42283f58 #0 id=0x7f060094 de.myexample.demo.ui.ListFragment} 
    at android.support.v4.app.FragmentManagerImpl.addFragment(SourceFile:1175) 
    at android.support.v4.app.BackStackRecord.run(SourceFile:616) 
    at android.support.v4.app.FragmentManagerImpl.execPendingActions(SourceFile:1460) 
    at android.support.v4.app.FragmentActivity.onStart(SourceFile:556) 
    at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1171) 
    at android.app.Activity.performStart(Activity.java:5143) 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2184) 
    ... 11 more 
java.lang.IllegalStateException: Fragment already added: ListFragment{42283f58 #0 id=0x7f060094 de.myexample.demo.ui.ListFragment} 
    at android.support.v4.app.FragmentManagerImpl.addFragment(SourceFile:1175) 
    at android.support.v4.app.BackStackRecord.run(SourceFile:616) 
    at android.support.v4.app.FragmentManagerImpl.execPendingActions(SourceFile:1460) 
    at android.support.v4.app.FragmentActivity.onStart(SourceFile:556) 
    at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1171) 
    at android.app.Activity.performStart(Activity.java:5143) 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2184) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261) 
    at android.app.ActivityThread.access$600(ActivityThread.java:141) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256) 
    at android.os.Handler.dispatchMessage(Handler.java:99) 
    at android.os.Looper.loop(Looper.java:137) 
    at android.app.ActivityThread.main(ActivityThread.java:5103) 
    at java.lang.reflect.Method.invokeNative(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:525) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 
    at dalvik.system.NativeStart.main(Native Method) 
+0

dove è setContentView fro l'attività? – Raghunandan

+0

prova a utilizzare tx.replace (R.id.MainFragmentContainer, listFragment); invece di utilizzare il metodo tx.add(). Leggi [questo] (http://developer.android.com/guide/components/fragments.html). per ulteriori informazioni sui frammenti –

+0

Grazie @Raghunandan. Ho aggiunto la riga mancante nel post. – creaity

risposta

12

Ok, risolto in conto mio.

Metto tutti i frammenti in onPause() e memorizzo lo stato in alcuni booleani. A seconda di quello, i frammenti vengono inseriti in onResume(). Il lancio è stabile indipendentemente dalla durata dell'attività in background.

boolean addList = false; 

@Override 
protected void onResume() { 
    FragmentTransaction tx = this.getSupportFragmentManager().beginTransaction(); 
    if (this.addList) { 
     ListFragment list = this.getListFragment(); 
     tx.add(R.id.MainFragmentContainer, list, "list_fragment_tag"); 
    } 

    tx.commit(); 
    super.onResume(); 

    this.addList = false; 

} 

@Override 
protected void onPause() { 
    this.addList = this.getListFragment().isAdded(); 
    ... 
    if (this.addList) { 
     FragmentTransaction tx = this.getSupportFragmentManager().beginTransaction(); 
     tx.remove(this.getListFragment()); 
     tx.commit(); 
    } 
    this.getSupportFragmentManager().executePendingTransactions(); 
    super.onPause(); 

} 

Forse che aiuta qualcuno con lo stesso problema

0

Il gestore Frammento salva il suo stato quando si esce. Quindi non devi aggiungere di nuovo il tuo frammento.

fare così:

protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(..); 

    if (savedInstanceState == null) { 
     ListFragment listFragment = this.getCaptureListFragment(); 
     FragmentTransaction tx = this.getSupportFragmentManager().beginTransaction(); 
     tx.add(R.id.MainFragmentContainer, listFragment, "list_fragment_tag"); 
     tx.commit(); 
    } 
} 
+0

Grazie per la risposta. Ha aiutato, ma non completamente. Su Android 4.1 fa il trucco. Ma su un dispositivo KitKat 4.4, l'attività è vuota e nessun frammento è visto. Ma sembra che in questo modo sia molto meglio della rimozione manuale. Forse, posso rimuovere il frammento a mano sui nuovi dispositivi all'interno del se ... Devo fare più test. Ma richiedono molto tempo, perché devo aspettare almeno 24 ore prima che arrivino i problemi – creaity

8

Per riprodurre questo, si potrebbe attivare "Non tenere le attività" in Impostazioni -> Opzioni sviluppatore. Quindi sospendi e riprendi l'attività.

che è così non c'è bisogno di aspettare 24 ore :)

+0

Non funziona per me :( –

-3

Non è necessario creare nuovo campo booleano per controllare lo stato aggiunta del frammento. C'è anche un metodo in frammento. Basta usarlo: myFragment.isAdded()

+0

Il booleano non è per memorizzare lo stato del frammento è stato aggiunto. memorizza lo stato precedente (vedi il mio metodo onPause()). Penso che tu non abbia capito il problema – creaity

+1

Sì, ho letto più attento ora Mi dispiace, hai ragione. – serefakyuz

Problemi correlati