FragmentPagerAdapter getItem no se llama

123

No puedo reutilizar fragmentos en FragmentPagerAdapter .. Usando el método destroyItem (), está eliminando el fragmento pero todavía no se llama getItem (). Solo hay 2-3 imágenes, así que estoy usando FragmentPagerAdapter en lugar de FragmentStatePagerAdapter ..

public class ExamplePagerAdapter extends FragmentPagerAdapter {

    ArrayList < String > urls;
    int size = 0;
    public ExamplePagerAdapter(FragmentManager fm, ArrayList < String > res) {
        super(fm);
        urls = res;
        size = urls.size();
    }

    @Override
    public int getCount() {
        if (urls == null) {
            return 0;
        } else {
            return size;
        }

    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        FragmentManager manager = ((Fragment) object).getFragmentManager();
        FragmentTransaction trans = manager.beginTransaction();
        trans.remove((Fragment) object);
        trans.commit();
    }

    @Override
    public Fragment getItem(int position) {

        Fragment fragment = new FloorPlanFragment();
        Bundle b = new Bundle();
        b.putInt("p", position);
        b.putString("image", urls.get(position));
        Log.i("image", "" + urls.get(position));
        fragment.setArguments(b);
        return fragment;
    }
}

Y en FragmentActivity,

pager.setAdapter(new ExamplePagerAdapter(getSupportFragmentManager(), res2)); 
Kanika
fuente
3
¿Hay alguna razón en particular que anulaste destroyItem()? Eso no es necesario.
CommonsWare
para inicializar nuevamente, use FragmentStatePagerAdapter también llame cuando lo anule super.destroyItem (contenedor, posición, objeto);
faiziii

Respuestas:

306

BESO Respuesta:

Uso simple FragmentStatePagerAdapter en lugar de FragmentPagerAdapter .

Obtuve la respuesta. En primer lugar, pensé en eliminar esta pregunta, ya que estoy cometiendo un error muy tonto, pero esta respuesta ayudará a alguien que se enfrenta al mismo problema que en lugar de FragmentPagerAdapterusar FragmentStatePagerAdapter.

Como @BlackHatSamurai mencionó en el comentario:

La razón por la que esto funciona es porque FragmentStatePagerAdapterdestruye como Fragmentos que no se están utilizando. FragmentPagerAdapterno.

Kanika
fuente
Muchas gracias. Nuestra respuesta me ayudó mucho.
Priya
1
Odio ser otro 'yo también' post, pero sí>. <Gracias por no eliminar la pregunta.
Paul Ruiz
34
La razón por la que esto funciona es porque FragmentStatePagerAdapter destruye como Fragmentos que no se están utilizando. FragmentPagerAdapter no lo hace.
BlackHatSamurai
3
Solo para referencia futura para aquellos que puedan encontrar esto mientras buscan un problema específico que están teniendo; lea en FragmentPagerAdapter y FragmentStatePagerAdapter. Se comportan de manera diferente por una razón y su uso específico puede requerir uno sobre el otro.
Chris Stewart
2
@najibputhawala Utilicé FragmentStatePagerAdapter pero todavía enfrento el mismo problema. getItem () no llamado
sam_k
168

El uso de FragmentStatePagerAdapterno solucionó por completo mi problema, que era un problema similar en el que onCreateViewno se solicitaban fragmentos secundarios en el visor de vistas. En realidad, estoy anidando mi FragmentPagerAdapterinterior de otro,Fragment por lo tanto, FragmentManagerse compartió en todos ellos y, por lo tanto, conservé instancias de los viejos fragmentos. La solución consistía en alimentar una instancia del getChildFragmentManageral constructor del FragmentPagerAdapteren mi fragmento de host. Algo como...

FragmentPagerAdapter adapter = new FragmentPagerAdapter(getChildFragmentManager());

El getChildFragmentManager()método es accesible a través de un fragmento y esto funcionó para mí porque devuelve un privado FragmentManagerpara ese fragmento específicamente para situaciones en las que se necesitan fragmentos de anidación. ¡Espero que esto ayude a alguien que pueda estar teniendo el mismo problema que yo!

  • Sin embargo, getChildFragmentManager()tenga en cuenta que usar su versión mínima de API debe ser al menos 17 (4.2), por lo que esto puede poner una llave en sus engranajes. Por supuesto, si está utilizando fragmentos de la biblioteca de soporte v4, debería estar bien.
Jraco11
fuente
25
Esta es la respuesta correcta. El problema se debe a que los fragmentos anidados en otros fragmentos deben usar getChildrenFragmentManager () en lugar de getFragmentManager ().
shihpeng
¡Muchas gracias, me llevó una eternidad encontrar esta respuesta!
Shpongoloid
Estoy de acuerdo con @shihpeng. Esta debería ser la respuesta correcta.
Raymond Lukanta
Este fue una solución para mí. Muchas gracias por enviar una respuesta
user3734429
Los documentos realmente deberían decir esto en el recorrido. Es muy realista que un ViewPager se cargue dentro de un fragmento. Gracias por publicar esta respuesta.
trabajó el
7

Anular long getItemId (int position)

FragmentPagerAdapteralmacena en caché los fragmentos que crea usando getItem. Estaba enfrentando el mismo problema, incluso después de que notifyDataSetChanged() getItemno se llamaba.

Esto es en realidad una característica y no un error. Debe anular getItemIdpara poder reutilizar correctamente sus fragmentos. Como está eliminando fragmentos, sus posiciones están cambiando. Como se menciona en los documentos:

long getItemId (int position)

Devuelve un identificador único para el artículo en la posición dada.

La implementación predeterminada devuelve la posición dada. Las subclases deberían anular este método si las posiciones de los elementos pueden cambiar.

Simplemente proporcione una identificación única para cada fragmento y ya está.

Utilizando una FragementStatePagerAdaptero regresar POSITION_NONEen el int getItemPosition (Object object)que está mal. No obtendrá ningún almacenamiento en caché.

vedant
fuente
Esta fue la respuesta correcta. Tuve que proporcionar diferentes identificadores para los fragmentos en getItemIdY ajustar getItemPositionpara devolver POSITION_NONESI el fragmento debe eliminarse. Tengo una bandera de enumeración para eso. Después de eso getItemserá llamado.
Murat Karagöz
Gracias @ MuratKaragöz por el +50 :)
vedant
5

Hice lo que @kanika y @ Jraco11 habían publicado, pero aún tenía el problema.

Entonces, después de muchos cambios, encontré uno que funcionó para mí y se agregó a mi FragmentPagerAdapter el siguiente código:

    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }

De acuerdo con lo que leí, getItemPosition se usa para notificar al ViewPager si actualizar o no un elemento, y para evitar actualizaciones si los elementos en las posiciones visibles no han cambiado.

Jorge Casariego
fuente
2

Hay dos escenarios diferentes: 1.) Tiene el mismo diseño para cada buscapersonas: en ese caso, será mejor si extiende su adaptador personalizado con PagerAdapter y devuelve un diseño único.

2.) Tiene un diseño diferente para cada buscapersonas: en ese caso, será mejor si extiende su adaptador personalizado con FragmentStatePagerAdapter y devuelve diferentes fragmentos para cada buscapersonas.

Maddy
fuente
2

El método getItem()se utiliza solo para crear nuevos elementos. Una vez que crearon, este método no se llamará. Si necesita obtener un artículo que es moneda en uso por el adaptador, use este método:

pagerAdapter.instantiateItem(viewPager, TAB_POS)
B-GangsteR
fuente
0

Descubrí que configurar un oyente en el diseño de tabulación impidió que se llamara a esto, probablemente porque solo tienen espacio para un oyente en tabLayout.setOnTabSelectedListenerlugar de una matriz de oyentes.

Oliver Dixon
fuente