8

No estoy familiarizado con FragmentPagerAdapter, por lo que esta será una de esas preguntas en las que (usted) leerá la descripción críticamente.FragmentPagerAdapter con ViewPager y dos fragmentos. Vaya al primero del segundo y actualice el texto del primer

Estructura: Tengo un FragmentPagerAdapter (código debajo), que contendrá dos fragmentos a la vez. El primero muestra extractos de libros, y el segundo una lista de títulos de libros.

Objetivo: Quiero lograr lo que se describe en el título: el usuario puede navegar hasta el segundo fragmento en el busca, hacer clic en un título, y luego quiero mover al usuario de nuevo al primer fragmento y dile al primer fragmento que actualice el texto. El primer fragmento tiene un método triggerRefresh para eso.

Código: Creo que mi problema ocurre debido a la manera en que FragmentPagerAdapter reutiliza/crea los Fragmentos (que no entiendo). Esta es mi clase:

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); 
     } 
    } 
} 

esto es cómo creé los miembros relevantes:

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

Y esto es lo que he tratado en otra parte de mi actividad, cuando recibo la llamada de retorno de los títulos de los libros fragmento con el título seleccionado:

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 de problemas:

Llamar al adaptador getView() no funcionará porque devolverá una nueva instancia de ExcerptsFragment, que no es la que está actualmente adjunta (como se esperaba, arroja la excepción).

He visto a mucha gente aquí (example) simplemente almacenando fragmentos en el getView(). ¿Está bien? Porque al mirar los ejemplos oficiales, me parece un antipatrón (derrota la referencia automática al mantener los elementos). Y esa es también la opinión here y here (y me parece a mí).

¿Alguna sugerencia? No me sorprendería si no entendiera todo esto ...

Respuesta

7

Descargo de responsabilidad: Aunque esto funcionó perfectamente bien para mí antes, , debe tener en cuenta las trampas clásicas de la función interna , comportamiento privado. Mientras escribía las pruebas que eventualmente me advertirían si la implementación interna cambiaba, desde entonces he pasado al greener pastures. Y tú deberías, también. Como tal, el valor de esta pregunta y su respuesta es solo histórica, en mi opinión.


Lo siento por esa pregunta, creo que fue la hora.

Para resolver ese problema, implementé this solution como está. Parece que funciona bien. Entonces, creo que solo fue cuestión de encontrar la instancia del fragmento (actualmente adjunta) al descubrir cómo se nombra su Id. El enlace de arriba explica cómo está hecho.

Opté por responder a mi propia pregunta en lugar de eliminarla porque creo que los novatos como yo en estos buscadores se beneficiarán de un "caso real". La mayoría de las respuestas que he visto hablan más acerca de la teoría, que es la manera correcta, por cierto ... pero sin un ejemplo real para trabajar, a veces la gente como yo se pierde.

De todos modos, aquí es la última pieza de código que necesitaba (la parte comentado más arriba):

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; 
} 

Por lo tanto, estoy teniendo la sensación de que esto es una solución robusta, porque no soy manteniendo cualquier referencia a fragmentos (arriesgándose así a que las referencias estén desactualizadas). Mantuve mi propio código al mínimo, por lo tanto, minimizando las posibilidades de que haga algo estúpido.

Por supuesto, si tiene algo que agregar, para mostrarnos, para decirnos qué hay de malo en hacerlo o qué se puede mejorar, me alegraría saber de usted.

+0

no debe confiar en la compatibilidad con el mecanismo interno de asignación de etiquetas. Vea mi respuesta a una pregunta similar sobre cómo hacer esto correctamente: http://stackoverflow.com/questions/14035090/how-to-get-existing-fragments-when-using-fragmentpageradapter/41345283#41345283 – morgwai

+0

@morgwai Gracias por la advertencia yo. Incluí un descargo de responsabilidad para advertir a los lectores potenciales. – davidcesarino

+0

de nada :) Sin embargo, creo que sería mejor proporcionar un enlace directamente a mi respuesta (no solo a esa pregunta) ya que mi respuesta es muy nueva y por lo tanto aún baja, así que los lectores pueden quedarse con uno de los 2 primeros respuestas puntuadas, ambas tienen problemas. (Agregué alguna explicación a mi respuesta por qué la solución que anula 'instanciateItem' puede no ser suficiente por sí misma) – morgwai

2

He buscado una solución a este problema un tiempo yo mismo. En principio, su enfoque funciona, pero romperá su código si alguna vez cambia el código de la creación de la etiqueta de fragmento en la implementación de la clase base de Android. ¡Esta es una dependencia bastante desagradable!

Un enfoque más elegante sería solucionar el problema y mantener una instancia de la actividad base en el fragmento. Implemente un setter para la etiqueta en su actividad y llámelo dentro del fragmento al momento de la creación, la etiqueta simplemente está disponible con getTag().

Se puede encontrar una implementación de ejemplo here.

+0

La mejor solución para este problema tan aleatorio hasta el momento. Sin embargo, hay dos cosas: puede obtener una referencia a la "actividad principal" con getActivity(). Y debe tener en cuenta que debe conservar los nombres de las etiquetas a través de los cambios de configuración, porque aunque el adaptador pueda ser recreado, los fragmentos probablemente no (y por lo tanto las etiquetas no se establecerán de nuevo). – jpm

Cuestiones relacionadas