2012-05-17 3 views
13

Sto sviluppando un'applicazione che ha fondamentalmente un ActionBar. Quando viene avviata la mia app, l'Activity crea i frammenti e li collega a ciascuna scheda, quindi quando si passa ottengo visualizzazioni diverse.Frammenti Android ricreati sul cambio di orientamento

I problemi sorgono quando provo a ruotare il dispositivo. Dopo una lotta, ho notato che Android ricrea automaticamente i frammenti aggiunti in precedenza in questo modo:

SummaryFragment.onCreate(Bundle) line: 79 
FragmentManagerImpl.moveToState(Fragment, int, int, int) line: 795 
FragmentManagerImpl.moveToState(int, int, int, boolean) line: 1032 
FragmentManagerImpl.moveToState(int, boolean) line: 1014  
FragmentManagerImpl.dispatchCreate() line: 1761 
DashboardActivity(Activity).onCreate(Bundle) line: 864 
... 

e poi ricreare i frammenti come al solito. Quindi ho i "veri" frammenti che mi aspetto di funzionare correttamente e le loro controparti "nascoste" create da Android che fanno crollare la mia app. Come posso evitare questo comportamento? Ho già provato a chiamare setRetainInstance (false) nel SummaryFragment.

Grazie

risposta

35

È necessario verificare la presenza di un savedInstanceState [edit: nella vostra attività genitore], e se esiste, non creare i tuoi frammenti.

+1

non so se fosse lo stesso problema di OP, ma questo è stato incredibilmente utile per me. Grazie. – ssmy

+0

Grazie mille @Barak ha funzionato solo dopo una settimana –

0

Se avete l'interfaccia utente simile (nessun file di layout-terra specifici) per entrambi gli orientamenti che è possibile impostare android:configChanges="keyboardHidden|orientation" all'attività nel file manifest.

Se non fornisci, per favore, il codice sorgente in cui stai aggiungendo i frammenti alle schede, e cercherò di aiutarti con miglioramenti.

+0

Parzialmente risolto con la risposta. Poiché la maggior parte del disegno viene eseguita in modo dinamico, rimuovo tutte le viste e le inoltro in base al nuovo orientamento. Onestamente, non penso che sia una soluzione pulita ma non riesco a impedire al sistema di creare selvaggiamente frammenti per me ... – Luke47

+0

Questo mi ha aiutato perché continuo a dimenticare di aggiornare i miei file di layout-land dopo aver cambiato Il ritratto. Mi hanno ottenuto circa 5 volte adesso. – buster

+3

Le cose brutte accadono quando si collega il dispositivo a un dock per auto, a una TV o ad altre modifiche alla configurazione: i frammenti verranno comunque ricreati. android: configChanges è malvagio, a meno che tu non sappia davvero cosa stai facendo. – personne3000

0

Quando si crea l'attività, verificare che non esista già. Se esiste, non fare nulla ... Android lo ricrea per te.

private void initFragment() { 
     FragmentManager fragMgr = getSupportFragmentManager(); 
     if (fragMgr.findFragmentByTag(LEADERBOARD_FRAG_TAG) != null) { return; } 
     frag = new HdrLeaderboardFragment(); 
     FragmentTransaction ft = fragMgr.beginTransaction(); 
     ft.replace(R.id.leaderboard_fragment_wrapper, frag, LEADERBOARD_FRAG_TAG); 
     ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); 
     ft.commit(); 
    } 
+1

Così facendo aggiunge ancora due frammenti ... quello che ho già avuto (nel modo in cui mi hai suggerito) più un altro che mi sta facendo letteralmente impazzire. Sarebbe stato così facile reimpostare FragmentManager tra i cambiamenti di orientamento ... – Luke47

0

Non sono sicuro se esiste una soluzione migliore, ma questo è ciò che ho fatto nell'ultimo programma.

Quando un frammento viene creato automaticamente dal sistema sulla modifica dell'orientamento e se si desidera tenerne traccia nell'attività dell'host, catturarli nel metodo dell'attività dell'host. E ottengono gli argomenti per impostazione predefinita, quindi puoi usarli per scoprire quale frammento è.

public void onAttachFragment(Fragment fragment) { 
    super.onAttachFragment(fragment); 
    if (fragment != null) { 
     if(fragment.getArguments() != null) { 
      switch (fragment.getArguments().getString(ARG_PARAM1)) { 
       case FragmentATag: 
        if (myFragmentA != fragment) { 
         myFragmentA = (FragmentA) fragment; 
        }      
        break; 
       case FragmentBTag: 
        if (myFragmentB != fragment) { 
         myFragmentB = (FragmentB) fragment; 
        }       
        break;     
      } 
     } 
    } 
    }