2012-05-13 16 views
9

Tengo un problema al hacer referencia a mis Fragmentos dentro de un ViewPager. Me gustaría hacerlo porque de mi actividad me gustaría actualizar un fragmento en una posición específica (por ejemplo, fragmento visualizado actualmente).Fragmentos de referencia dentro de ViewPager

Actualmente tengo algo como esto:

public static class MyPagerAdapter extends FragmentPagerAdapter { 

    private static final String TAG = "MyPagerAdapter"; 
    private static HashMap<Integer, EventListFragment> mPageReferenceMap = new HashMap<Integer, EventListFragment>(); 

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

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

    @Override 
    public Fragment getItem(int position) { 
     Log.i(TAG, "getItem: "+position); 
     int dateOffset = position-1; 
     EventListFragment mFragment = EventListFragment.newInstance(dateOffset); 
     mPageReferenceMap.put(position, mFragment); 
     return mFragment; 
    } 

    @Override 
    public void destroyItem(ViewGroup container, int position, Object object) { 
     Log.i(TAG, "destroyItem: "+position); 
     mPageReferenceMap.remove(position); 
     super.destroyItem(container, position, object); 
    } 


    public EventListFragment getFragment(int key) { 
     Log.i(TAG, "Size of pager references: "+mPageReferenceMap.size()); 
     return mPageReferenceMap.get(key); 
    } 
} 

El problema es que el destroyItem() es llamado más a menudo que getItem(), así que me quedo con referencias nulas. Si no uso destroyItem() para borrar las referencias a los fragmentos destruidos ... bueno, haré referencia a los fragmentos que no existen.

¿Hay alguna buena manera de referenciar los fragmentos que se crean con EventListFragment mFragment = EventListFragment.newInstance(dateOffset);? ¿O qué debería hacer para actualizar un fragmento dentro de una ViewPager de mi actividad (desde el menú de opciones para ser preciso)?

Respuesta

5

Pude resolverlo. El truco era hacer una lista de referencias dentro de Activity, no PagerAdapter. Dice así:

List<WeakReference<EventListFragment>> fragList = new ArrayList<WeakReference<EventListFragment>>(); 

@Override 
public void onAttachFragment (Fragment fragment) { 
    Log.i(TAG, "onAttachFragment: "+fragment); 
    if(fragment.getClass()==EventListFragment.class){ 
     fragList.add(new WeakReference<EventListFragment>((EventListFragment)fragment)); 
    } 
} 
public EventListFragment getFragmentByPosition(int position) { 

    EventListFragment ret = null; 
    for(WeakReference<EventListFragment> ref : fragList) { 
     EventListFragment f = ref.get(); 
     if(f != null) { 
      if(f.getPosition()==position){ 
       ret = f; 
      } 
     } else { //delete from list 
      fragList.remove(f); 
     } 
    } 
    return ret; 

} 

Por supuesto, su fragmento tiene para implementar una función getPosition(), pero necesitaba algo como esto de todos modos, así que no era un problema.

Gracias Alex Lockwood por su sugerencia con WeakReference!

+0

Acabo de terminar mi final y decidí volver y ver si conseguía que las cosas funcionaran ... me alegro de poder ayudar (incluso si no fue con el problema principal: P). –

+0

Pregunta: ¿no debería pasar la llamada fragList.remove() a la referencia débil, en lugar del fragmento? – gcl1

+0

@Michael: Empecé a usar un enfoque como este, y funciona bastante bien. Pero dado que fragList contiene referencias débiles, parece que las entradas están sujetas a la recolección de elementos no utilizados, aunque aún pueda necesitarlos. He visto que el método getFragmentByPosition() a veces devuelve nulo, así que creo que eso es lo que está sucediendo. ¿Alguna idea de cómo evitar eso? Gracias. – gcl1

3

Dos cosas:

  1. añadir la siguiente línea en su método de Actividad onCreate (o donde usted hace funcionar su ViewPager):

    mPager.setOffscreenPageLimit(NUM_ITEMS-1); 
    

    Esto evitará que las páginas adicionales fuera de la pantalla en la memoria (es decir, evitando que se destruyan), incluso cuando no se muestran actualmente en la pantalla.

  2. Se podría considerar la implementación de su HashMap de modo que sostenga WeakReference<Fragment> s en lugar de los mismos Fragment s. Tenga en cuenta que esto requeriría que cambie su método de getFragment de la siguiente manera:

    WeakReference<Fragment> weakRef = mPageReferenceMap.get(position); 
    return (weakRef != null) ? weakRef.get() : null; 
    

    Esto no tiene nada que ver con su problema ... es sólo algo que me di cuenta y pensé que iba a traer a su atención. Mantener WeakReferences en su Fragment s le permitirá aprovechar la capacidad del recolector de basura para determinar la accesibilidad para usted, por lo que no tiene que hacerlo usted mismo.

+0

En cuanto a la 2. => no va a resolver mi problema, pero es probable que sea una buena idea para evitar fugas, gracias. Y 1. => Tendré 7 páginas, tal vez más en el futuro, ¿está bien mantenerlas todas en la memoria al mismo tiempo? –

+0

Hmm ... obviamente, cuanto menos 'Fragment's guardes en la memoria, mejor. Si desea acceder a su 'Fragment's on demand desde su' Activity' (sin cambiar realmente a la página 'Fragment's) sin tenerlos todos en la memoria, la solución sería un truco. Puede ser necesario explorar el código fuente 'ViewPager' y ver cómo maneja el ciclo de vida' Fragment'. No conozco ninguna forma de hacerlo, pero lo investigaré cuando tenga más tiempo. –

+0

Puedo sugerir humildemente, si hay algo que necesitas obtener de un Fragmento mientras está fuera de la pantalla, tal vez no deberías dárselo a un Fragmento.Considere ponerlo en un Servicio o Proveedor de Contenido, y deje que su Fragmento sea un cliente para él. – Sparky

Cuestiones relacionadas