2012-12-17 7 views
10

Ho un piccolo problema: ho un ViewPager con alcune pagine e uso FragmentStatePagerAdapter per gestire i dati. In portrait ho per esempio 20 pagine per ViewPager e in landscape ho solo 10 pagine per ViewPager. Quindi su un cambio di orientamento creo un nuovo adattatore con dati diversi.ViewPager + FragmentStatePagerAdapter + cambio di orientamento

Ecco una piccola spiegazione del perché: mostro un'immagine in verticale e due in orizzontale ma sempre tutte in valore. Se ho 10 foto da mostrare, ne ho 10 in verticale e 5 in orizzontale (sempre in due).

ma ora ho uno strano bug: Quando sono in Paesaggio sull'indice 5 e spegnere il dispositivo, pagina corrente del ViewPager è impostato a 10. Se mi rivolgo di nuovo indietro io sono a pagina 5. Se i swipe il ViewPage ora a pagina 10 il metodo getItem dell'adattatore non viene mai chiamato e il ViewPage mi mostra l'immagine di un ritratto e non i due per il paesaggio. Come può accadere? C'è una cache nell'adattatore o in ViewPager? Nel onCreate dell'attività viene creato tutto, l'adattatore e anche i dati (solo stringhe con percorso) per ViewPager. Quindi qualche idea su come risolvere questa "caratteristica" davvero spaventosa?

Ecco alcuni codice:

onCreate:

mViewPagerAdapter = new ReaderPageViewAdapter(getSupportFragmentManager(), getBaseContext(), mCurrentDocument.mPages, getResources() 
       .getConfiguration().orientation); 
    mPageReader = (ReaderViewPager) findViewById(R.id.pager); 
    mPageReader.setAdapter(mViewPagerAdapter); 

adattatore getItem:

public Fragment getItem(final int index) { 
     final PageInfo pageInfo = mPages.get(index); 
     final PageFragment pageFragment = (PageFragment) PageFragment 
       .instantiate(mContext, pageInfo.mClss.getName(), pageInfo.mArgs); 
     return pageFragment; 
    } 

Se avete bisogno di qualcosa di più mi dica. Grazie

+0

Per me questo http://stackoverflow.com/questions/17629463/fragmentpageradapter-how-to-handle-orientation-changes approccio si adatta perfettamente! – r4m

risposta

41

È possibile ignorare il FragmentActivity onSaveInstanceState() e non chiamare il super.onSaveInstanceState() nel metodo .

@Override 
protected void onSaveInstanceState(final Bundle outState) { 
    // super.onSaveInstanceState(outState); 
} 

Non utilizzaremViewPager.setSaveEnabled(false);

si è conclusa con un grande memoryLeak. Dopo ogni cambio di orientamento, mette i Frammenti in una serie di FragmentManager e non lo pulisce mai. Quindi aumenta di oltre 100 MB l'utilizzo della memoria dopo aver cambiato l'orientamento molte volte. Utilizzare il metodo onSaveInstanceState è un modo migliore che penso.

+0

Devo verificare che setSaveEnabled mi abbia causato 6 ore di debugging della perdita di memoria. –

+0

Siamo spiacenti di chiedere così tardi ma hai mai scoperto cosa in super.onSaveInstanceState (outState) stava causando questo comportamento inaspettato? Grazie in anticipo ! ;-) – 2Dee

+0

Sì, è tardi :-) in onSaveInstanceState ha salvato i frammenti in una matrice, che non viene mai pulita. Senza chiamare super, non salva i frammenti in questo array. – Informatic0re

-1

Solo voi utilizzare in viewPager.setonpagechangelistener e attuare per richiedere il codice applicare la vostra applicazione,

http://developer.android.com/reference/android/support/v4/view/ViewPager.html

+0

già implementare il OnPageChangeListener ma non voglio fare tutto il lavoro lì. Penso che ci sia solo una cache o qualcosa che ho bisogno di cancellare Forse del ViewPager o FragmentManager L'adattatore è completamente nuovo, il ViewPage è r ecreato con findViewById, quindi perché qualcosa salva una cache? Forse è lo stato salvato, ma non so come cancellarlo. – Informatic0re

0

Mi sono anche verificato questo problema e ho trovato il motivo.

mai schermata ruotato, Il FragmentManager manterrà tutte le attività di frammenti ospitati, E wou't rimuovere frammenti Se si utilizza FragmentStatePagerAdapter, è possibile utilizzare FragmentManager.getFragments() per controllare il numero di frammenti.

Esempio: l'attività ha 4 frammenti, dopo 4 cambi di orientamento, la dimensione dell'elenco FragmentManager.getFragments() sarà !

ho trovato alcune soluzioni:

  1. non chiamare il super.onSaveInstanceState() di voi attività, ma è non sembra una buona soluzione, Frammenti non può salvare lo stato e il ripristino.

  2. Uso FragmentPagerAdapter invece di FragmentStatePagerAdapter. Ma dopo l'orientamento è cambiato, i frammenti che ViewPager ospitati è stato nascosto (Qualcun altro ha lo stesso problema?). Ma posso rimuovere tutti i frammenti in Activity.onCreate per ripararlo. in questo modo:

    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        FragmentManager fm = getSupportFragmentManager(); 
        List<Fragment> fragments = fm.getFragments(); 
        if (fragments != null) { 
         FragmentTransaction transaction = fm.beginTransaction(); 
         for (Fragment fragment : fragments) { 
          transaction.detach(fragment).remove(fragment); 
         } 
         transaction.commitNowAllowingStateLoss(); 
        } 
        ... 
    

    Ma la Fragment.onCreateView() chiamato due volte.

Sto ancora cercando la soluzione perfetta: D

Edit:
ho finalmente risolto il problema, E 'causa con la mia ViewPager è aggiungere dopo onStart. Quando si esegue onStart, The FragmentManager proverà a ripristinare lo stato dei frammenti. Ho rintracciato in FragmentManager, Avere questi codice:

com/android/support/support-fragment/24.2.1/support-fragment-24.2.1-sources.jar!/android/support/v4/app/FragmentManager.java

Controllare la linea di evidenziazione, il f.mContainerId in realtà è la mia ViewPager id. Quindi proverà ad aggiungere la vista dei frammenti a ViewPager. Nel mio caso, il ViewPager non è ancora aggiunto, quindi verrà oscurato, ma lo stato dei frammenti è ATTACHED. E in FragmentPagerAdapter.instantiateItem(), se è stato aggiunto il frammento, E 'solo che attach il frammento, ma il frammento è già collegato, quindi il suo non fare nulla :(

aggiungo ViewPager a XML layout di attività, la sua fissa.

Felice codifica: D