8

Non ho familiarità con FragmentPagerAdapter, quindi questa sarà una di quelle domande che noi (tu) leggiamo criticamente la descrizione.FragmentPagerAdapter con ViewPager e due frammenti. Vai al primo dal secondo e aggiorna il primo testo

Struttura: Ho un FragmentPagerAdapter (codice di seguito), che conterrà due frammenti alla volta. Il primo mostra estratti di libri e il secondo un elenco di titoli di libri.

Obiettivo: voglio ottenere ciò che è descritto nel titolo: l'utente può navigare per il secondo frammento nel pager, clicca su un titolo, e poi voglio spostare l'utente di nuovo al primo frammento e dire al primo frammento di aggiornare il testo. Il primo frammento ha un metodo triggerRefresh per quello.

Codice: Credo che il mio problema si verifichi a causa del modo in cui riordina/crea i frammenti FragmentPagerAdapter (che non capisco). Questa è la mia classe:

static class MyFragmentPagerAdapter extends FragmentPagerAdapter { 

    public MyFragmentPagerAdapter(FragmentManager fm) { 
     super(fm); 
    } 

    @Override 
    public int getCount() { 
     return NUM_ITEMS; 
    } 

    @Override 
    public Fragment getItem(int position) { 
     switch(position) { 
     case 0: 
      return new ExcerptsFragment(); 
     case 1: 
      return new BookListFragment(); 
     default: 
      throw new IllegalArgumentException("not this many fragments: " + position); 
     } 
    } 
} 

Ecco come ho creato i membri rilevanti:

ViewPager mViewPager = (ViewPager) findViewById(R.id.pager); 
MyFragmentPagerAdapter mFragmentPagerAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager()); 
mViewPager.setAdapter(mFragmentPagerAdapter); 

E questo è quello che ho provato altrove nella mia attività, quando ricevo la richiamata dai titoli di libri frammento con il titolo selezionato:

mViewPager.setCurrentItem(0); // back to excerpts screen page. It's OK. 
// Here's the problem! How to identify the fragment 0 
// to ExcerptsFragment and call its triggerRefresh()?!? 

serie di problemi:

La chiamata dell'adattatore getView() non funzionerà perché restituirà una nuova istanza di ExcerptsFragment, che non è quella attualmente collegata (come previsto, genera l'eccezione).

Ho visto molte persone qui (example) solo memorizzando i frammenti nel getView(). È giusto? Perché guardando gli esempi ufficiali, mi sembra un anti-modello per me (sconfiggere il riferimento automatico tenendo gli oggetti). E questo è anche il parere here e here (e mi sembra giusto).

Qualche suggerimento? Non sarei sorpreso se non capisco tutto questo un po '...

risposta

7

Disclaimer: Anche se questo ha funzionato perfettamente bene per me prima, si dovrebbe essere consapevoli delle classiche insidie ​​di dipendere da interni , comportamento privato. Mentre scrivevo test che alla fine mi avrebbero avvertito se l'implementazione interna fosse cambiata, da allora sono passato a greener pastures. E anche tu dovresti. In quanto tale, il valore di questa domanda e la sua risposta sono solo storici, secondo me.


Mi dispiace per questa domanda, penso che era l'ora.

Per risolvere questo problema, ho implementato this solution così com'è. Sembra funzionare bene. Quindi, credo che si trattasse solo di trovare l'istanza del frammento (attualmente collegato) capendo come viene chiamato il suo id. Il link sopra spiega come è fatto.

Ho optato per rispondere alla mia domanda invece di eliminarla perché credo che i novizi come me su questi cercapersone beneficeranno di uno "scenario caso reale". La maggior parte delle risposte che ho visto parlano molto della teoria, che è la strada giusta per BTW ... ma senza un vero esempio su cui lavorare a volte le persone come me si perdono.

In ogni caso, qui è l'ultimo pezzo di codice che mi serviva (la parte commentato sopra):

int n = 0; 
mViewPager.setCurrentItem(n); // in the question I had stopped here. 

ExcerptsFragment f = (ExcerptsFragment) ContainerActivity.this 
     .getSupportFragmentManager().findFragmentByTag(getFragmentTag(n)); 
f.triggerRefresh(); 

// ... below the helper method: used the solution from the link. 

private String getFragmentTag(int pos){ 
    return "android:switcher:"+R.id.pager+":"+pos; 
} 

Quindi, sto avendo la sensazione che questa è una soluzione robusta, perché io non sono tenendo qualsiasi riferimento a frammenti (rischiando così che i riferimenti siano obsoleti). Ho mantenuto il mio codice al minimo, riducendo quindi al minimo le possibilità che io facessi qualcosa di stupido.

Ovviamente, se hai qualcosa da aggiungere, da mostrarci, per dire cosa è sbagliato nel farlo o cosa può essere migliorato, sarò lieto di sentirti.

+0

non si deve fare affidamento sulla compatibilità con il meccanismo interno di assegnazione dei tag. Vedere la mia risposta a una domanda simile a come farlo correttamente: http://stackoverflow.com/questions/14035090/how-to-get-existing-fragments-when-using-fragmentpageradapter/41345283#41345283 – morgwai

+0

@morgwai Grazie per l'avvertimento me. Ho incluso un disclaimer per avvertire i potenziali lettori. – davidcesarino

+0

siete i benvenuti :) Penso comunque sarebbe meglio fornire un link direttamente alla mia risposta (non solo a quella domanda) in quanto la mia risposta è molto nuova e quindi ancora bassa, quindi i lettori potrebbero rimanere bloccati con uno dei 2 migliori ha ottenuto delle risposte, entrambe con problemi. (Ho aggiunto alcune spiegazioni alla mia risposta, perché la soluzione che sovrascrive 'instantiateItem' potrebbe non essere sufficiente) – morgwai

2

Ho cercato una soluzione a questo problema un po 'di tempo. Il tuo approccio in linea di principio funziona, ma romperà il tuo codice se mai il codice della creazione del tag frammento nell'implementazione della classe base Android cambia. Questa è una dipendenza abbastanza brutta!

Un approccio più elegante sarebbe quello di trasformare il problema e mantenere un'istanza della tua attività di base nel tuo frammento. Implementa un setter per il tag nella tua attività e chiamalo all'interno del frammento al momento della creazione: il tag è semplicemente disponibile con getTag().

È possibile trovare un'implementazione di esempio here.

+0

La migliore soluzione per questo problema molto casuale finora. Tuttavia due cose: puoi ottenere un riferimento all '"attività principale" con getActivity(). E devi tenere a mente che è necessario mantenere i nomi dei tag attraverso le modifiche di configurazione, perché anche se l'adattatore potrebbe essere ricreato, i frammenti probabilmente non lo sono (e quindi i tag non saranno nuovamente impostati) – jpm

Problemi correlati