Referencia de fragmentos dentro de ViewPager
Tengo un problema con referenciar mis Fragmentos dentro de un ViewPager. Me gustaría hacerlo porque de mi actividad me gustaría actualizar un fragmento en una posición especificada (por ejemplo, fragmento que se muestra actualmente).
Actualmente tengo algo como esto:
- ViewPager con múltiples instancias de fragmentos de la misma clase
- Establecer la orientación para sólo 1 fragmento en mi actividad, mientras que el resto está en el retrato
- Diferencia entre onResume () y onResumeFragments ()
- Android Espresso: ¿Cómo puedo probar un Fragmento específico al seguir una actividad a varios fragmentos de arquitectura
- Cómo cargar matriz de cadena en un fragmento?
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()
se llama con más frecuencia que getItem()
, así que me quedan con referencias nulas. Si no utilizo destroyItem()
para borrar referencias a fragmentos destruidos … bueno, hago referencia a fragmentos que no existen.
¿Hay alguna manera agradable de referencia a los fragmentos que se crean con EventListFragment mFragment = EventListFragment.newInstance(dateOffset);
? ¿O qué debo hacer para actualizar un fragmento dentro de un ViewPager desde mi actividad (desde el menú de opciones para ser preciso)?
- Viewpageindicator dentro del fragmento
- OnCreateView se llama varias veces / Trabajo con ActionBar y Fragmentos
- RecyclerView onBindViewHolder sólo se llama una vez dentro del diseño de la pestaña
- Mostrar diálogo de progreso dentro de DialogFragment
- ANDROID: ViewPager con diferentes fragmentos en el método instantiateItem
- Hacer fragmentos a pantalla completa mediante programación
- NavigationView cómo manejar contenido de encabezado dinámico
- IllegalArgumentException: No se encontró ninguna vista para id para fragmento - ViewPager en ViewPager
Me las arreglé para solucionarlo. El truco era hacer una lista de referencia dentro de la actividad, 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 que implementar una función getPosition()
, pero yo necesitaba algo como esto de todos modos, por lo que no era un problema.
Gracias Alex Lockwood por su sugerencia con WeakReference
!
Dos cosas:
-
Agregue la siguiente línea en el método
onCreate
su actividad (o dondequiera que inicialice su ViewPager):mPager.setOffscreenPageLimit(NUM_ITEMS-1);
Esto mantendrá las páginas fuera de pantalla adicionales en memoria (es decir, evitando que se destruyan), incluso cuando no se muestren en la pantalla.
-
Podrías considerar la implementación de tu
HashMap
modo que contengaWeakReference<Fragment>
s en lugar de los propiosFragment
. Tenga en cuenta que esto requeriría que cambias tu métodogetFragment
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 traería a su atención. Mantener las
WeakReferences
a suFragment
le permitirá aprovechar la capacidad del recolector de basura para determinar la accesibilidad para usted, por lo que no tiene que hacerlo usted mismo.