2014-05-25 10 views
6

Ho un FragmentStatePagerAdapter con 6 frammenti all'interno.FragmentStatePagerAdapter onPageEvento selezionato

Ogni frammento si collega al server e carica i dati.

In questo momento, la connessione al server è in corso in Fragment.onStart(), ciò significa che in qualsiasi momento, ho 3 richieste HTTP in corso (il frammento selezionato e uno su ciascun lato).

Quello che voglio è quello di avere una sola connessione in quel momento, così ho capire di usare

viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() 
{ 
    @Override 
    public void onPageSelected(final int position) 
    { 
     CustomFragment fragment = (CustomFragment) myFragmentStatePagerAdapter.getItem(position); 

     fragment.onSelected();//do stuff in here 
    } 
}); 

Il fatto è che, getItem() restituisce una nuova istanza del frammento, non ancora aggiunto al gestore (e quindi, non ancora vista creata, ecc.).

Inoltre, ho provato setUserVisibleHint(boolean isVisibleToUser) ma non viene chiamata in visibile, solo su isVisibleToUser = false

Quindi, come per ottenere una "onPageSelected()" evento per il frammento?

Grazie in anticipo

+0

È possibile utilizzare AsyncTask con un esecutore SERIAL. http://developer.android.com/reference/android/os/AsyncTask.html#SERIAL_EXECUTOR Avrai 1 cosa in esecuzione alla volta, ma può fare la coda. Assicurati di chiamare cancel() nel tuo onStop, non esegui attività che non ti servono più – whizzle

+0

Puoi ancora usare 'OnPageChangeListener', ma per accedere al frammento avrai bisogno di un approccio diverso. Dai un'occhiata a questa domanda http://stackoverflow.com/questions/7379165/update-data-in-listfragment-as-part-of-viewpager?lq=1 – Luksprog

risposta

7

La soluzione migliore per voi sarebbe quella di ignorare setUserVisibleHint(). Assicurati di estendere FragmentPagerAdapter. Dal suo source code puoi vederlo chiamare setUserVisibleHint(true) anche per i frammenti visibili. Lo uso sempre e funziona bene.

// adapter 
public static class PlayerAdapter extends FragmentStatePagerAdapter { 
    public PlayerAdapter(FragmentManager fm) { 
     super(fm); 
    } 

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

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

// fragment 
public class SimpleFragment extends Fragment { 

    private static final String TAG = BookControlsFragment.class.getSimpleName(); 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     return inflater.inflate(R.layout.fragment_simple, container, false); 
    } 

    @Override 
    public void setUserVisibleHint(boolean isVisibleToUser) { 
     super.setUserVisibleHint(isVisibleToUser); 
     Log.d(TAG, "setUserVisibleHint: " + isVisibleToUser); 
    } 
} 
+0

lo hai usato in combinazione con FragmentStatePagerAdapter (non solo normale adattatore)? Perché sto testandolo in questo momento e non funziona (non funziona significa, solo chiamandolo su "false") – Cheborra

+0

Appena ricontrollato. Ho sostituito FragmentPageAdapter con FragmentStatePageAdapter. setUserVisibleHint() funziona bene. Il frammento visibile riceve "vero". Prova a utilizzare frammenti vuoti molto semplici con il metodo sovrascritto setUserVisibleHint (boolean isVisibleToUser). Vedrai che il metodo viene chiamato con "true" per il frammento visibile. Aggiornerò la risposta con un esempio –

+0

scopre che il problema era che stavo avvolgendo l'adattatore attorno a un altro adattatore (adattatore infinito) e che il wrapper non implementava il metodo "setPrimaryItem()" e quindi, "setUserVisibleHint (true)" non veniva mai chiamato . Ad ogni modo, accetterò questa risposta (e darò una taglia) perché mi ha indirizzato nella giusta direzione. – Cheborra

1

Che cosa ha funzionato per me è, nel metodo di mio adattatore cercapersone getItem, per salvare in un elenco il mio riferimento al frammento personalizzato torno. Il contratto che sembrano seguire sia l'adattatore del cercapersone frammento che l'adattatore del cercapersone dello stato dei frammenti indica che l'ultimo frammento restituito da getItem(i) sarà il frammento corretto da aggiornare nel metodo onPageSelected(i).

Ho solo provato questa tecnica con un adattatore per cercapersone frammento e un numero ragionevolmente piccolo di schede. Con un adattatore per cercapersone di stato sarebbero necessari alcuni test per vedere se conservare i riferimenti ai frammenti fa aumentare l'uso della memoria.

0

Nella tua FragmentStatePagerAdapter uso un HashMap per contenere i frammenti creati, allora si può l'accesso in un secondo momento dal contenitore viewpager (attività o frammento):

public class CustomFragmentPagerAdapter extends FragmentStatePagerAdapter { 

    private HashMap<Integer, CustomFragment> fragMap = 
     new HashMap<Integer, CustomFragment>(); 

    ... 

    @Override 
    public Fragment getItem(int position) { 
     CustomFragment frag = new CustomFragment(); 
     ... 
     fragMap.put(position, frag); 
     return frag; 
    } 

    @Override 
    public void destroyItem(ViewGroup container, int position, Object object) { 
     super.destroyItem(container, position, object); 
     fragMap.remove(position); 
    } 

    public CustomFragment getFragment(int position) { 
     return fragMap.get(position); 
    } 
    ... 
} 

Ora, nel vostro contenitore viewpager (attività o frammento):

private int lastPage = 0; 

... 

viewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { 
    @Override 
    public void onPageSelected(int position) { 

     CustomFragment fragment; 
     int currentPage = viewPager.getCurrentItem(); 

     /* connect the current fragment and disconnect the previous one, in case 
      you actually need to disconnect it from the server, 
      otherwise just connect the current fragment.*/ 
     if(currentPage > lastPage) { 
      fragment = yourPagerAdapter.getFragment(currentPage - 1); 
      fragment.disconnect(); 
      fragment = yourPagerAdapter.getFragment(currentPage); 
      fragment.connect(); 
     } else { 
      fragment = yourPagerAdapter.getFragment(currentPage + 1); 
      fragment.disconnect(); 
      fragment = yourPagerAdapter.getFragment(currentPage); 
      fragment.connect(); 
     } 
     lastPage = currentPage; 
    } 
}); 

Dal momento che l'onPageChangeListener non si chiama quando si avvia l'applicazione, è necessario collegare il primo frammento. L'importante è che tu abbia un riferimento ai frammenti restituiti da getItem() utilizzando yourPagerAdapter.getFragment(currentPage).

Edit:

Penso che questo possa essere una logica più per il metodo onPageSelected() callback:

viewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { 
     @Override 
     public void onPageSelected(int position) { 

      CustomFragment fragment; 
      int currentPage = viewPager.getCurrentItem(); 
      Set<Integer> myKeySet = yourPagerAdapter.getKeys(); 
      for(Integer key : myKeySet) { 
       if(key == currentPage) { 
        fragment = yourPagerAdapter.getFragment(key); 
        fragment.connect(); 
       } else { 
        fragment = yourPagerAdapter.getFragment(key); 
        fragment.disconnect(); 
       } 
      } 

     } 
    }); 

Ma è necessario implementare questo methd su FragmentStatePagerAdapter:

public Set<Integer> getKeys() { 
    return fragMap.keySet(); 
} 

e sbarazzarsi del membro dei dati lastPage.

Problemi correlati