2013-10-27 12 views
13

recente ho iniziato a utilizzare i frammenti hanno creato un'applicazione demo che assomiglia a questo:Come salvare e riutilizzare la stessa istanza di frammenti?

Demo App

Cliccando su ogni pulsante si alterna tra frammento 1, Frammento 2, e 3. Frammento

Quello che sono cercare di ottenere è di avere solo 1 istanza di ciascun frammento e riutilizzarla. (Si noti che tutti i frammenti sono creati e aggiunti dinamicamente). Attualmente sto facendo questo creando una HashMap di frammenti e inserendo ogni istanza e afferrandola da lì.

Quindi le mie domande sono: C'è un modo migliore per farlo: utilizzando il metodo putFragment (...) di FragmentManager? putFragment (Bundle bundle, String key, Fragment fragment) Non riesco a capire come usarlo nel mio caso. Se qualcuno può darmi un esempio di come usare questo metodo.

È costoso mantenere un riferimento di ogni frammento nella mia attività? Questo mantiene tutti i frammenti vivi? Sto usando un riferimento morbido per affrontare questo, ma non sono sicuro se questo è il modo corretto di farlo. Per favore indicami un modo alternativo per farlo o fammi sapere se questo è il modo migliore per farlo.

Grazie in anticipo.

Ecco il mio codice:

UPDATE: Sto cercando di riutilizzare frammenti dalla pila di nuovo, cercando di aggiungere solo loro se non esiste nella pila avanti. Il codice qui sotto mi dà l'eccezione di Stato illegali dopo a navigare lontano dal frammento di una -> tornano ad esso -> quindi provare a premere il pulsante indietro:

10-28 13:21:40.255: ERROR/MessageQueue-JNI(3548): java.lang.IllegalStateException: Fragment already added: FragmentOne{423db570 #0 id=0x7f050006 fragOne} 

public class MainActivity extends Activity implements View.OnClickListener { 

private Button btnOne; 
private Button btnTwo; 
private Button btnThree; 

/* Called when the activity is first created. 
    */ 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    initialize(); 
    if(findViewById(R.id.fl) != null){ 
     if(savedInstanceState != null) 
      return; 
    } 

    FragmentManager.enableDebugLogging(true); 
    updateView("fragOne"); 
} 

private void initialize(){ 
    btnOne = (Button) findViewById(R.id.button1); 
    btnTwo = (Button) findViewById(R.id.button2); 
    btnThree = (Button) findViewById(R.id.button3); 
    btnOne.setOnClickListener(this); 
    btnTwo.setOnClickListener(this); 
    btnThree.setOnClickListener(this); 
    fragHolder = new HashMap<String, SoftReference<Fragment>>(); 
} 

private void updateView(String tag){ 
    FragmentTransaction ft = getFragmentManager().beginTransaction(); 
    Fragment frag = getFragmentManager().findFragmentByTag(tag); 

    boolean addToStack = true; 
    if(frag == null){ 
     if(tag.equals("fragOne")) 
      frag = new FragmentOne();  
     else if(tag.equals("fragTwo")) 
      frag = new FragmentTwo(); 
     else if(tag.equals("fragThree")) 
      frag = new FragmentThree(); 
    }else{ 
     //Don't add to back stack 
     addToStack = false; 
    } 
    ft.replace(R.id.fl, frag, tag); 
    if(addToStack) 
     ft.addToBackStack(null); 
    ft.commit(); 
} 

    @Override 
    public void onClick(View v) { 
     switch(v.getId()){ 
      case R.id.button1: 
       updateView("fragOne"); 
       break; 
      case R.id.button2: 
       updateView("fragTwo"); 
       break; 
      case R.id.button3: 
       updateView("fragThree"); 
       break; 
     } 
    } 
} 
+0

Hai esaminato FragmentTransactions? Possono esserti utili. –

risposta

2

per dimostrare una FragmentTransaction, il seguente esempio può essere utile tu.

In primo luogo, si desidera eseguire tutte le operazioni di inizializzazione nello onCreate() della propria attività, che è corretto, ma verranno apportate alcune modifiche.

public class MainActivity extends Activity implements View.OnClickListener { 

private Button btnOne; 
private Button btnTwo; 
private Button btnThree; 

/* Called when the activity is first created.*/ 
@Override 
public void onCreate(Bundle savedInstanceState) 
{ 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    initialize(); 
    if(findViewById(R.id.fl) != null) 
    { 
     if(savedInstanceState != null) 
     { 
      FragmentTransaction trans = getFragmentManager().beginTransaction(); 

      //This is where we add our first fragment 
      trans.add(R.id.fl, new FragmentOne()); 
      trans.commit(); 
     } 
    } 
} 

private void initialize() 
{ 
    btnOne = (Button) findViewById(R.id.button1); 
    btnTwo = (Button) findViewById(R.id.button2); 
    btnThree = (Button) findViewById(R.id.button3); 
    btnOne.setOnClickListener(this); 
    btnTwo.setOnClickListener(this); 
    btnThree.setOnClickListener(this); 
} 

public void onClick(View view) 
{ 
    //Here is where we'll actually transfer the fragments 

    FragmentTransaction trans = getFragmentManager().beginTransaction(); 
    switch(v.getId()){ 
     case R.id.button1: 
      trans.replace(R.id.fl, new FragmentOne()); 
      trans.addToBackStack(null); 
      trans.commit(); 
      break; 
     case R.id.button2: 
      trans.replace(R.id.fl, new FragmentTwo()); 
      trans.addToBackStack(null); 
      trans.commit(); 
      break; 
     case R.id.button3: 
      trans.replace(R.id.fl, new FragmentThree()); 
      trans.addToBackStack(null); 
      trans.commit(); 
      break; 
    } 
} 

Ciò consentirà di passare facilmente da un frammento al successivo.

+0

Grazie per la risposta. Inizialmente ho provato questo approccio, tuttavia questo aggiunge ogni transazione al backstack facendogli aumentare di dimensioni per ogni transazione. Come ho già detto, la memoria è un problema nella mia app vera e propria. Quindi voglio limitare il numero di voci nel back stack. Immagino che una domanda migliore sarebbe: Se è possibile utilizzare il backstack come coda FIFO -> dopo 10 transazioni scartare la prima quando si aggiunge 11. – Naveed

+1

Puoi chiamare 'disallowAddToBackStack()' e tenere traccia di un intero statico o qualcosa del genere quando ci sono troppe cose nello stack posteriore. –

+0

Grazie anche per aver risolto l'eccezione di stato illegale che stavo ottenendo. Ancora bisogno di lavorare su non aggiungere lo stesso frammento se ci sei già ma è abbastanza semplice. – Naveed

1

FragmentManager esegue la gestione della memoria. Ucciderà/ricrea o manterrà in memoria le istanze secondo la sua logica. Puoi assicurarti che lo stato del tuo frammento sia salvato usando onSaveInstanceState()

Oppure puoi forzare il sistema a mantenere in vita l'istanza usando setRetainInstance(true) sul frammento.

Ecco come si crea una transazione.

FragmentTransaction fragmentTransaction = context.getSupportFragmentManager().beginTransaction(); 
    fragmentTransaction.replace(R.id.layout, new MyFragment(), f.getClass().getName()); 
    fragmentTransaction.commit(); 
+1

Grazie per la risposta. Prima stavo provando questo approccio, l'unica differenza che ho notato è che se si digita qualcosa nel frammento uno, e poi lo si sostituisce con il frammento due, creando una nuova istanza di frammento uno quando si naviga indietro si causa di perdere quel cambiamento come riuso la stessa istanza (nel qual caso il testo sarà ancora lì) – Naveed

Problemi correlati