2014-09-19 13 views
9

UPDATERimozione di frammenti di FragmentStatePagerAdapter

Dopo un po 'maggiore di combattimento con questo problema e l'aiuto di modo che gli utenti sono riuscito a risolverlo. Ecco come il mio clearProgressUpTo sembra ora.

public void clearProgressUpTo(int progress) { 
    boolean deleted = false; 

    for (int i = fragments.size() - 1; i > 0; i--) { 
     int key = fragments.keyAt(i); 
     if (key != progress) { 
      fragments.delete(key); 
      deleted = true; 
     } else { 
      break; 
     } 
    } 

    if (deleted) 
     notifyDataSetChanged(); //prevents recursive call (and IllegalStateException: Recursive entry to executePendingTransactions) 

    while (mSavedState.size() > progress) { 
     mSavedState.remove(mSavedState.size()-1); 
    } 

} 

Il motivo per cui lo sto facendo dopo notifyDataSetChanged perché il initiateItem stava riempiendo il mio mSavedState ancora una volta. E sono sicuro che dopo aver notificato il mio adapter non possiedo nessuna di queste Fragments.

Inoltre, se si vuole fare in quel modo cambiare il vostro mSaveState-protected in modo da essere in grado di ottenere dalla classe che estende (nel mio caso VerticalAdapter).

Ho dimenticato di dire che sto usando FragmentStatePagerAdapter fix by Adam Speakman per risolvere il mio problema.

////////////////////////////////////////////// /////// DOMANDA PARTE /////////////////////////////////////// ///////////////

il problema che sto avendo è che ho bisogno di rimuovere completamente alcuni di Fragments detenuti in FragmentStatePagerAdapter.

Ho già eseguito la correzione POSITION_NONE ma i vecchi frammenti sembrano rimanere intatti.

COSTRUZIONE

perché la costruzione di mia ViewPager è insolito sono stato costretto a mettere Dentro il mio VerticalAdater estende FragmentStatePagerAdapter un SparseArray che contiene tutti i miei frammenti.

public class VerticalAdapter extends FragmentStatePagerAdapter { 

private SparseArray<Fragment> fragments = new SparseArray<Fragment>(); 
... 

@Override 
public Fragment getItem(int position) { 
    return getFragmentForPosition(position); 
} 

@Override 
public int getCount() { 
    return fragments.size(); 
} 

PROBLEMA

ho fatto un metodo specifico incaricato di annullamento di tutta la Fragments fino a un certo punto della mia FragmentStatePagerAdapter. Funziona bene ma il problema di cui non posso sbarazzarmi è di azzerare lo ArrayList all'interno di FragmentStatePagerAdapter. Anche se svuoto lo SparseArray, lo ArrayList di FragmentStatePagerAdapter che il mio numero VerticalAdapter è ancora in attesa del Fragments che non voglio avere lì. Per questo motivo quando creo nuovo Fragments hanno lo stato di quelli vecchi.

public void clearProgressUpTo(int progress) { 
    boolean deleted = false; 

    for (int i = fragments.size() - 1; i > 0; i--) { 
     int key = fragments.keyAt(i); 
     if (key != progress) { 
      fragments.delete(key); 
      deleted = true; 
     } else { 
      break; 
     } 
    } 

    if (deleted) 
     notifyDataSetChanged(); //prevents recursive call (and IllegalStateException: Recursive entry to executePendingTransactions) 
} 

Se avete bisogno di più informazioni/codice prego di dirmi nei commenti cercherò di fornire quante più informazioni possibile.

Non ho idea di come risolvere questo problema, quindi qualsiasi input sarebbe apprezzato.

EDIT

Aggiunta richiesto il codice.

private Fragment getFragmentForPosition(int position) { 
    return fragments.get(getKeyForPosition(position)); 
} 

public int getKeyForPosition(int position) { 
    int key = 0; 
    for (int i = 0; i < fragments.size(); i++) { 
     key = fragments.keyAt(i); 
     if (i == position) { 
      return key; 
     } 
    } 
    return key; 
} 
+0

post 'getFragmentForPosition (posizione);' per favore. – mmlooloo

+0

Aggiunto il codice richiesto. – JakubW

+0

L'unica cosa che manca qui dal mio 'Adatper' è il metodo' setProgress' che riempie l'array 'frammenti'. Perché conosco il suo vecchio stato? Perché 'setProgress' sta ricaricando l'intero array' framments' con 'newinstance' dei miei' Fragments'. Anche gli ID di 'Fragments' all'interno della matrice' ViewPager' sono gli stessi di prima di 'setProgress'. – JakubW

risposta

7

FragmentStatePageAdapter salva lo stato del frammento mentre lo distrugge, in modo che quest'ultimo quando viene ricreato il frammento verrà applicato lo stato salvato.

Lo stato del frammento è memorizzato in una variabile membro privata. Quindi non possiamo estendere l'implementazione corrente per aggiungere la funzionalità di rimozione dello stato salvato.

Ho clonato l'attuale implementazione FragmentStatePagerAdapter e ho incluso la funzionalità di rimozione dello stato salvata. Ecco lo gist reference.

/** 
    * Clear the saved state for the given fragment position. 
    */ 
    public void removeSavedState(int position) { 
     if(position < mSavedState.size()) { 
      mSavedState.set(position, null); 
     } 
    } 

nel metodo clearProgressUpTo, ogni volta che si rimuove il frammento di matrice sparsa, chiamare questo metodo, che cancella fuori lo stato salvato per quel frammento.

+0

Ho risolto il mio problema ieri ed è collegato alla tua risposta. Ho preso mSaveState da FragmentStatePagerAdapter e ho utilizzato mSaveState.remove sugli elementi di cui mi sto liberando. Accettare la tua risposta perché è la più vicina a risolvere questo problema. – JakubW

+0

Ciao JakubW ... potresti condividere la tua risposta – amity

7

Il problema non è causato dall'utilizzo di SparseArray. In effetti, si incontra un bug di FragmentStatePagerAdapter. Ho trascorso qualche tempo a leggere il codice sorgente di FragmentStatePagerAdapter, ViewPager e FragmentManagerImpl e poi trovato il motivo per cui i nuovi frammenti hanno lo stato di quelli vecchi:

Il FragmentStatePagerAdapter salvare il sate dei tuoi vecchi frammenti quando rimuoverli, e se aggiungi nuovi frammenti all'adattatore in un secondo momento, lo stato salvato verrà passato al nuovo frammento nella stessa posizione.

I Googled questo problema e trovare una soluzione, qui è il suo link: http://speakman.net.nz/blog/2014/02/20/a-bug-in-and-a-fix-for-the-way-fragmentstatepageradapter-handles-fragment-restoration/

Il codice sorgente può essere trovato qui: https://github.com/adamsp/FragmentStatePagerIssueExample/blob/master/app/src/main/java/com/example/fragmentstatepagerissueexample/app/FixedFragmentStatePagerAdapter.java

L'idea chiave di questa soluzione è quello di riscrivere la FragmentStatePagerAdapter e utilizzare un tag String per identificare ciascun frammento nell'adattatore. Poiché ogni frammento ha un tag diverso, è facile identificare un nuovo frammento, quindi non passare uno stato salvato a un nuovo frammento.

Infine, ringraziare Adam Speakman, autore di tale soluzione.

+0

Ho usato questa correzione di bug prima di postare su SO e non ha risolto il problema: C Ho intenzione di dargli un altro colpo tho e postare i miei risultati. – JakubW

+0

Forse ho frainteso il tuo problema, controllerò il tuo post e chiarirò dopo averlo risolto. –

+0

Sto provando ad usarlo ma per ora il problema si verifica ancora. Comunque sembra aggiustare qualcos'altro per me. Ma c'è un altro problema con questa soluzione. Quando estendo i miei '' frammenti' da '{1, 2, 3, 7}' a '{1, 2, 3, 4, 7}' il TAG non viene inserito nel nuovo 'Frammento' (4). La cosa strana è che funziona dopo la rotazione dello schermo. – JakubW

Problemi correlati