Cómo obtener fragmentos existentes cuando se usa FragmentPagerAdapter

99

Tengo problemas para hacer que mis fragmentos se comuniquen entre sí a través de Activity, que está usando FragmentPagerAdapter, como una clase auxiliar que implementa la gestión de pestañas y todos los detalles de la conexión de un ViewPagerasociado TabHost. He implementado FragmentPagerAdapterlo mismo que lo proporciona el proyecto de ejemplo de Android Support4Demos .

La pregunta principal es ¿cómo puedo obtener un fragmento particular FragmentManagercuando no tengo ni una identificación ni una etiqueta? FragmentPagerAdapterestá creando los fragmentos y generando automáticamente la identificación y las etiquetas.

Ismar Slomic
fuente
@ jk2K ¿cómo puede ser esto un duplicado de una pregunta que se hizo un año después
Davi
@Dawit duplicado como una etiqueta, no relacionado con el tiempo, las preguntas posteriores tienen vistas más altas
jk2K
La mayoría de las respuestas aquí no funcionan en producción, así que verifique mi respuesta en stackoverflow.com/a/54280113/2413303
EpicPandaForce

Respuestas:

194

Resumen del problema

Nota: En esta respuesta voy a hacer referencia FragmentPagerAdaptery su código fuente. Pero la solución general también debería aplicarse a FragmentStatePagerAdapter.

Si está leyendo esto, probablemente ya sepa que FragmentPagerAdapter/ FragmentStatePagerAdapterestá destinado a crear Fragmentspara usted ViewPager, pero después de la recreación de la actividad (ya sea desde la rotación de un dispositivo o el sistema matando su aplicación para recuperar memoria), estos Fragmentsno se crearán nuevamente, sino que instancias recuperadas deFragmentManager . Ahora diga sus Activitynecesidades para obtener una referencia a estos Fragmentspara trabajar en ellos. No tiene un ido tagpara estos creados Fragmentsporque los FragmentPagerAdapter configuró internamente . Entonces, el problema es cómo obtener una referencia a ellos sin esa información ...

Problema con las soluciones actuales: confiar en el código interno

Muchas de las soluciones que he visto en esta y otras preguntas similares se basan en conseguir una referencia a la existente Fragmentllamando FragmentManager.findFragmentByTag()e imitando la etiqueta creada internamente:"android:switcher:" + viewId + ":" + id . El problema con esto es que está confiando en el código fuente interno, que como todos sabemos no garantiza que siga siendo el mismo para siempre. Los ingenieros de Android en Google podrían decidir fácilmente cambiar la tagestructura que rompería su código dejándolo incapaz de encontrar una referencia al existente Fragments.

Solución alternativa sin depender de internos tag

Aquí hay un ejemplo simple de cómo obtener una referencia al Fragmentsdevuelto por FragmentPagerAdapterque no se basa en el tagsconjunto interno de Fragments. La clave es anular instantiateItem()y guardar referencias allí en lugar de hacerlogetItem() .

public class SomeActivity extends Activity {
    private FragmentA m1stFragment;
    private FragmentB m2ndFragment;

    // other code in your Activity...

    private class CustomPagerAdapter extends FragmentPagerAdapter {
        // other code in your custom FragmentPagerAdapter...

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

        @Override
        public Fragment getItem(int position) {
            // Do NOT try to save references to the Fragments in getItem(),
            // because getItem() is not always called. If the Fragment
            // was already created then it will be retrieved from the FragmentManger
            // and not here (i.e. getItem() won't be called again).
            switch (position) {
                case 0:
                    return new FragmentA();
                case 1:
                    return new FragmentB();
                default:
                    // This should never happen. Always account for each position above
                    return null;
            }
        }

        // Here we can finally safely save a reference to the created
        // Fragment, no matter where it came from (either getItem() or
        // FragmentManger). Simply save the returned Fragment from
        // super.instantiateItem() into an appropriate reference depending
        // on the ViewPager position.
        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            Fragment createdFragment = (Fragment) super.instantiateItem(container, position);
            // save the appropriate reference depending on position
            switch (position) {
                case 0:
                    m1stFragment = (FragmentA) createdFragment;
                    break;
                case 1:
                    m2ndFragment = (FragmentB) createdFragment;
                    break;
            }
            return createdFragment;
        }
    }

    public void someMethod() {
        // do work on the referenced Fragments, but first check if they
        // even exist yet, otherwise you'll get an NPE.

        if (m1stFragment != null) {
            // m1stFragment.doWork();
        }

        if (m2ndFragment != null) {
            // m2ndFragment.doSomeWorkToo();
        }
    }
}

o si prefiere trabajar con tagsvariables / referencias de miembros de clase en lugar de, Fragmentstambién puede tomar el tagsconjunto de FragmentPagerAdapterla misma manera: NOTA: esto no se aplica a FragmentStatePagerAdapterya que no se establece tagsal crear su Fragments.

@Override
public Object instantiateItem(ViewGroup container, int position) {
    Fragment createdFragment = (Fragment) super.instantiateItem(container, position);
    // get the tags set by FragmentPagerAdapter
    switch (position) {
        case 0:
            String firstTag = createdFragment.getTag();
            break;
        case 1:
            String secondTag = createdFragment.getTag();
            break;
    }
    // ... save the tags somewhere so you can reference them later
    return createdFragment;
}

Tenga en cuenta que este método NO se basa en imitar el tagconjunto interno de FragmentPagerAdaptery, en su lugar, utiliza las API adecuadas para recuperarlos. De esta manera, incluso si los tagcambios en futuras versiones de la SupportLibrary, seguirás estando seguro.


No olvide que, dependiendo del diseño de su Activity, el en el Fragmentsque está tratando de trabajar puede o no existir todavía, por lo que debe tenerlo en cuenta haciendo nullverificaciones antes de usar sus referencias.

Además, si en cambio está trabajando con FragmentStatePagerAdapter, entonces no desea mantener referencias duras a su Fragmentsporque es posible que tenga muchas de ellas y las referencias duras las guardarían innecesariamente en la memoria. En su lugar, guarde las Fragmentreferencias en WeakReferencevariables en lugar de en las estándar. Me gusta esto:

WeakReference<Fragment> m1stFragment = new WeakReference<Fragment>(createdFragment);
// ...and access them like so
Fragment firstFragment = m1stFragment.get();
if (firstFragment != null) {
    // reference hasn't been cleared yet; do work...
}
Tony Chan
fuente
3
Esta es una solución realmente buena, pero parece perder su efectividad si no sabe cuántos fragmentos se pasarán.
Riot Goes Woof
3
@Zorpix puede almacenar los fragmentos creados en un HashMap: map.put (posición, createdFragment);
Tom Bevelander
12
¡Esto merece la marca de verificación! Una forma muy inteligente y completa de lograr esto. Me has ayudado mucho gracias!
young_souvlaki
2
Al principio, esta solución parecía demasiado complicada, así que la salté. Sin embargo, finalmente volví a eso porque las otras respuestas no eran satisfactorias. Y no fue tan difícil como pensaba.
Suragch
1
no es necesario anular nada y, en realidad , no debería anular instantiateItem. la forma correcta de hacer esto es llamar instantiateItem al onCreatemétodo de su actividad rodeado por startUpdatey finishUpdate. Vea mi respuesta para más detalles
morgwai
82

Encontré la respuesta a mi pregunta basada en la siguiente publicación: reutilización de fragmentos en un adaptador de página de fragmentos

Pocas cosas he aprendido:

  1. getItem(int position)en el FragmentPagerAdapternombre bastante engañoso de lo que realmente hace este método. Crea nuevos fragmentos, no devuelve los existentes. En ese sentido, el método debería cambiarse de nombre a algo parecido createItem(int position)al SDK de Android. Entonces este método no nos ayuda a obtener fragmentos.
  2. De acuerdo con la explicación en la publicación, el soporte FragmentPagerAdapterholds hace referencia a fragmentos antiguos , debe dejar la creación de los fragmentos al FragmentPagerAdaptery, por lo tanto, no tiene ninguna referencia a los Fragmentos o sus etiquetas. Sin embargo, si tiene una etiqueta de fragmento, puede recuperar fácilmente la referencia a ella FragmentManagerllamando findFragmentByTag(). Necesitamos una forma de averiguar la etiqueta de un fragmento en la posición de página determinada.

Solución

Agregue el siguiente método auxiliar en su clase para recuperar la etiqueta del fragmento y enviarla al findFragmentByTag()método.

private String getFragmentTag(int viewPagerId, int fragmentPosition)
{
     return "android:switcher:" + viewPagerId + ":" + fragmentPosition;
}

¡NOTA! Este es un método idéntico al que se FragmentPagerAdapterutiliza al crear nuevos fragmentos. Vea este enlace http://code.google.com/p/openintents/source/browse/trunk/compatibility/AndroidSupportV2/src/android/support/v2/app/FragmentPagerAdapter.java#104

Ismar Slomic
fuente
Por cierto, hay más sobre el tema en estas preguntas y respuestas: stackoverflow.com/questions/6976027/…
Thomas
1
¿Qué es el parámetro de entrada viewId? ¿Qué vista?
Nilzor
@Nilzor viewId es el ID de ViewPager.
Dr.jacky
¿Quizás en lugar de adivinar la etiqueta, el fragmento podría indicar su etiqueta a su actividad onAttach()?
cuenca
4
Ésta no es la forma correcta. La respuesta de @Tony Chan es la mejor y la forma correcta.
Morteza Rastgoo
16

no necesita anular instantiateItemni depender de la compatibilidad con el makeFragmentNamemétodo interno creando manualmente etiquetas de fragmento.
instantiateItemEs un público método por lo que puede y de hecho debe llamar en onCreateel método de su actividad rodeado con llamadas a startUpdatey finishUpdatemétodos descritos en el PagerAdapter javadoc :

Una llamada al método startUpdate de PagerAdapter (ViewGroup) indica que el contenido de ViewPager está a punto de cambiar. Seguirán una o más llamadas a instanciarItem (ViewGroup, int) y / o destroyItem (ViewGroup, int, Object), y el final de una actualización será señalado por una llamada a finishUpdate (ViewGroup).

Luego, por medio de lo anterior, puede almacenar referencias a instancias de sus fragmentos en vars locales si lo necesita. Ver ejemplo:

public class MyActivity extends AppCompatActivity {

    Fragment0 tab0; Fragment1 tab1;

    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.myLayout);
        ViewPager viewPager = (ViewPager) findViewById(R.id.myViewPager);
        MyPagerAdapter adapter = new MyPagerAdapter(getSupportFragmentManager());
        viewPager.setAdapter(adapter);
        ((TabLayout) findViewById(R.id.tabs)).setupWithViewPager(viewPager);

        adapter.startUpdate(viewPager);
        tab0 = (Fragment0) adapter.instantiateItem(viewPager, 0);
        tab1 = (Fragment1) adapter.instantiateItem(viewPager, 1);
        adapter.finishUpdate(viewPager);
    }

    class MyPagerAdapter extends FragmentPagerAdapter {

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

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

        @Override public Fragment getItem(int position) {
            if (position == 0) return new Fragment0();
            if (position == 1) return new Fragment1();
            return null;  // or throw some exception
        }

        @Override public CharSequence getPageTitle(int position) {
            if (position == 0) return getString(R.string.tab0);
            if (position == 1) return getString(R.string.tab1);
            return null;  // or throw some exception
        }
    }
}

instantiateItemprimero intentará obtener referencias a instancias de fragmentos existentes de FragmentManager. Solo si aún no existen, creará nuevos utilizando el getItemmétodo de su adaptador y los "almacenará" en el FragmentManagerpara cualquier uso futuro.

Es importante tener en cuenta que incluso si no necesita obtener referencias a sus fragmentos, aún debe llamar instantiateItema todas sus pestañas rodeadas por startUpdate/ finishUpdateen su onCreatemétodo de esta manera:

    adapter.startUpdate(viewPager);
    // ignoring return values of the below 2 calls, just side effects matter:
    adapter.instantiateItem(viewPager, 0);
    adapter.instantiateItem(viewPager, 1);
    adapter.finishUpdate(viewPager);

Si no lo hace, entonces usted está en riesgo de que sus casos de fragmentos no se comprometen a FragmentManager: cuando su actividad se convierte en primer plano instantiateItemse llamará automáticamente para obtener sus fragmentos, pero startUpdate/ finishUpdate pueden no (dependiendo de los detalles de implementación) y lo que básicamente hacer es comenzar / confirmar a FragmentTransaction.
Esto puede provocar que las referencias a las instancias de fragmentos creadas se pierdan muy rápidamente (por ejemplo, cuando gira la pantalla) y se vuelvan a crear con mucha más frecuencia de la necesaria. Dependiendo de cuán "pesados" sean sus fragmentos, puede tener consecuencias de rendimiento no despreciables.
Además, en tal caso, las instancias de fragmentos almacenados en vars locales puedense vuelve obsoleto: si la plataforma Android intenta obtenerlos FragmentManagerpor cualquier motivo, fallará y, por lo tanto, creará y usará nuevos, mientras que sus vars seguirán haciendo referencia a los antiguos.

Morgwai
fuente
1
Podría ser la mejor solución en algunos casos. Pero, ¿qué pasará si FragmentManger mata el fragmento y lo vuelve a escribir?
woltran
1
@woltran FragmentManagerno puede simplemente matar al azar ( destruir es la palabra correcta aquí) su Fragment(piense en lo que sucedería si decidiera matar un Fragmentque se está mostrando actualmente;)). En general, el ciclo de vida de a Fragmentestá vinculado a su Activity(consulte github.com/xxv/android-lifecycle para obtener más detalles) -> a Fragmentsolo se puede destruir si Activityse destruyó. En tal caso, cuando un usuario de vuelta navega a lo dado Activitysu onCreateserán llamados de nuevo y una nueva instancia de la Fragmentse creará.
morgwai
Esta es la respuesta REAL
MJ Studio
¿Realmente debería crear fragmentos en lugar de confiar en que se creen cuando un usuario se desplaza por ViewPager, por ejemplo?
Yar
@Yar sí, realmente deberías. El extracto de documentos que proporcioné lo dice claramente y la sección "Información adicional" explica por qué.
morgwai
11

La forma en que lo hice es definir una tabla hash de WeakReferences de la siguiente manera:

protected Hashtable<Integer, WeakReference<Fragment>> fragmentReferences;

Luego escribí el método getItem () así:

@Override
public Fragment getItem(int position) {

    Fragment fragment;
    switch(position) {
    case 0:
        fragment = new MyFirstFragmentClass();
        break;

    default:
        fragment = new MyOtherFragmentClass();
        break;
    }

    fragmentReferences.put(position, new WeakReference<Fragment>(fragment));

    return fragment;
}

Entonces puedes escribir un método:

public Fragment getFragment(int fragmentId) {
    WeakReference<Fragment> ref = fragmentReferences.get(fragmentId);
    return ref == null ? null : ref.get();
}

Esto parece funcionar bien y lo encuentro un poco menos complicado que el

"android:switcher:" + viewId + ":" + position

truco, ya que no depende de cómo se implementa FragmentPagerAdapter. Por supuesto, si el fragmento ha sido liberado por FragmentPagerAdapter o si aún no se ha creado, getFragment devolverá un valor nulo.

Si alguien encuentra algún problema con este enfoque, los comentarios son más que bienvenidos.

personne3000
fuente
int fragmentIddebería cambiarse el nombre aint position
lmaooooo
7
Estaba usando un enfoque muy similar. Pero esto falla cuando el buscapersonas se crea a partir de un paquete SavedState. Por ejemplo: la actividad pasa a segundo plano y vuelve a primer plano después de que se llama a onSavedStateInstance (). En ese caso, no se llamará a los métodos getItem ().
Anoop
¿Cuál es la razón para crear su propio mapa, ya que hay uno en FragmentManager que siempre es up2date? Vea mi respuesta para más detalles.
morgwai
Además, el hecho de que un fragmento haya sido destruido no garantiza que no haya referencias sólidas a él (aunque es probable, pero NO garantizado), en cuyo caso su mapa aún contendría fragmentos obsoletos.
morgwai
1
Esto no funcionará correctamente después de que el sistema vuelva a crear los Fragmentos.
EpicPandaForce
10

Creé este método que me funciona para obtener una referencia al fragmento actual.

public static Fragment getCurrentFragment(ViewPager pager, FragmentPagerAdapter adapter) {
    try {
        Method m = adapter.getClass().getSuperclass().getDeclaredMethod("makeFragmentName", int.class, long.class);
        Field f = adapter.getClass().getSuperclass().getDeclaredField("mFragmentManager");
        f.setAccessible(true);
        FragmentManager fm = (FragmentManager) f.get(adapter);
        m.setAccessible(true);
        String tag = null;
        tag = (String) m.invoke(null, pager.getId(), (long) pager.getCurrentItem());
        return fm.findFragmentByTag(tag);
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } 
    return null;
}
Pepijn
fuente
Es bueno recordar haber creado el Método y el Campo fuera del método para un mejor rendimiento
Marcos Vasconcelos
2

la solución sugerida por @ personne3000 es agradable, pero tiene un problema: cuando la actividad pasa a un segundo plano y el sistema la elimina (para obtener algo de memoria libre) y luego se restaura, fragmentReferencesestará vacía, porque getItemno sería llamado.

La siguiente clase maneja tal situación:

public abstract class AbstractHolderFragmentPagerAdapter<F extends Fragment> extends FragmentPagerAdapter {

    public static final String FRAGMENT_SAVE_PREFIX = "holder";
    private final FragmentManager fragmentManager; // we need to store fragment manager ourselves, because parent's field is private and has no getters.

    public AbstractHolderFragmentPagerAdapter(FragmentManager fm) {
        super(fm);
        fragmentManager = fm;
    }

    private SparseArray<WeakReference<F>> holder = new SparseArray<WeakReference<F>>();

    protected void holdFragment(F fragment) {
        holdFragment(holder.size(), fragment);
    }

    protected void holdFragment(int position, F fragment) {
        if (fragment != null)
            holder.put(position, new WeakReference<F>(fragment));
    }

    public F getHoldedItem(int position) {
        WeakReference<F> ref = holder.get(position);
        return ref == null ? null : ref.get();
    }

    public int getHolderCount() {
        return holder.size();
    }

    @Override
    public void restoreState(Parcelable state, ClassLoader loader) { // code inspired by Google's FragmentStatePagerAdapter implementation
        super.restoreState(state, loader);
        Bundle bundle = (Bundle) state;
        for (String key : bundle.keySet()) {
            if (key.startsWith(FRAGMENT_SAVE_PREFIX)) {
                int index = Integer.parseInt(key.substring(FRAGMENT_SAVE_PREFIX.length()));
                Fragment f = fragmentManager.getFragment(bundle, key);
                holdFragment(index, (F) f);
            }
        }
    }

    @Override
    public Parcelable saveState() {
        Bundle state = (Bundle) super.saveState();
        if (state == null)
            state = new Bundle();

        for (int i = 0; i < holder.size(); i++) {
            int id = holder.keyAt(i);
            final F f = getHoldedItem(i);
            String key = FRAGMENT_SAVE_PREFIX + id;
            fragmentManager.putFragment(state, key, f);
        }
        return state;
    }
}
netimen
fuente
1

El principal obstáculo para manejar los fragmentos es que no puede confiar en getItem (). Después de un cambio de orientación, las referencias a los fragmentos serán nulas y no se volverá a llamar a getItem ().

Este es un enfoque que no depende de la implementación de FragmentPagerAdapter para obtener la etiqueta. Anule instantiateItem () que devolverá el fragmento creado a partir de getItem () o encontrado desde el administrador de fragmentos.

@Override
public Object instantiateItem(ViewGroup container, int position) {
    Object value =  super.instantiateItem(container, position);

    if (position == 0) {
        someFragment = (SomeFragment) value;
    } else if (position == 1) {
        anotherFragment = (AnotherFragment) value;
    }

    return value;
}
Adán
fuente
0

Vea esta publicación sobre cómo devolver fragmentos del FragmentPagerAdapter. Depende de que conozca el índice de su fragmento, pero esto se establecería en getItem () (solo en la instanciación)

Comunidad
fuente
0

Me las arreglé para resolver este problema usando identificadores en lugar de etiquetas. (Estoy usando que definí FragmentStatePagerAdapter que usa mis Fragmentos personalizados en los que anulé el método onAttach, donde guardas la identificación en algún lugar:

@Override
public void onAttach(Context context){
    super.onAttach(context);
    MainActivity.fragId = getId();
}

Y luego accedes al fragmento fácilmente dentro de la actividad:

Fragment f = getSupportFragmentManager.findFragmentById(fragId);
usuario2740905
fuente
0

No sé si este es el mejor enfoque, pero nada más funcionó para mí. Todas las demás opciones, incluido getActiveFragment, devolvieron un valor nulo o provocaron que la aplicación se bloqueara.

Noté que en la rotación de la pantalla el fragmento se estaba adjuntando, así que lo usé para enviar el fragmento de regreso a la actividad.

En el fragmento:

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    try {
        mListener = (OnListInteractionListener) activity;
        mListener.setListFrag(this);
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString()
                + " must implement OnFragmentInteractionListener");
    }
}

Luego en la actividad:

@Override
public void setListFrag(MyListFragment lf) {
    if (mListFragment == null) {
        mListFragment = lf;
    }
}

Y finalmente en la actividad onCreate ():

if (savedInstanceState != null) {
    if (mListFragment != null)
        mListFragment.setListItems(items);
}

Este enfoque une el fragmento visible real a la actividad sin crear uno nuevo.

TacoEater
fuente
0

No estoy seguro de si mi método era la mejor o correcta para hacer esto, ya que soy un principiante relativo con Java / Android, pero funcionó (estoy seguro de que viola los principios orientados a objetos, pero ninguna otra solución funcionó para mi caso de uso).

Tuve una actividad de alojamiento que estaba usando un ViewPager con un FragmentStatePagerAdapter. Para obtener referencias a los Fragmentos que fueron creados por FragmentStatePagerAdapter, creé una interfaz de devolución de llamada dentro de la clase de fragmento:

public interface Callbacks {
    public void addFragment (Fragment fragment);
    public void removeFragment (Fragment fragment);
}

En la actividad de hosting implementé la interfaz y creé un LinkedHasSet para realizar un seguimiento de los fragmentos:

public class HostingActivity extends AppCompatActivity implements ViewPagerFragment.Callbacks {

    private LinkedHashSet<Fragment> mFragments = new LinkedHashSet<>();

    @Override
    public void addFragment (Fragment fragment) {
        mFragments.add(fragment);
    }

    @Override
    public void removeFragment (Fragment fragment) {
        mFragments.remove(fragment);
    }
}

Dentro de la clase ViewPagerFragment agregué los fragmentos a la lista dentro de onAttach y los eliminé dentro de onDetach:

public class ViewPagerFragment extends Fragment {

    private Callbacks mCallbacks;

    public interface Callbacks {
        public void addFragment (Fragment fragment);
        public void removeFragment (Fragment fragment);
    } 

    @Override
    public void onAttach (Context context) {
        super.onAttach(context);
        mCallbacks = (Callbacks) context;
        // Add this fragment to the HashSet in the hosting activity
        mCallbacks.addFragment(this);
    }

    @Override
    public void onDetach() {
        super.onDetach();
        // Remove this fragment from the HashSet in the hosting activity
        mCallbacks.removeFragment(this);
        mCallbacks = null;
    }
}

Dentro de la actividad de alojamiento, ahora podrá usar mFragments para iterar a través de los fragmentos que existen actualmente en FragmentStatePagerAdapter.

sbearben
fuente
0

Esta clase hace el truco sin depender de etiquetas internas. Advertencia: Se debe acceder a los fragmentos utilizando el método getFragment y no getItem.

public class ViewPagerAdapter extends FragmentPagerAdapter {

    private final Map<Integer, Reference<Fragment>> fragments = new HashMap<>();
    private final List<Callable0<Fragment>> initializers = new ArrayList<>();
    private final List<String> titles = new ArrayList<>();

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

    void addFragment(Callable0<Fragment> initializer, String title) {
        initializers.add(initializer);
        titles.add(title);
    }

    public Optional<Fragment> getFragment(int position) {
        return Optional.ofNullable(fragments.get(position).get());
    }

    @Override
    public Fragment getItem(int position) {
        Fragment fragment =  initializers.get(position).execute();
        return fragment;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Fragment fragment = (Fragment) super.instantiateItem(container, position);
        fragments.put(position, new WeakReference<>(fragment));
        return fragment;
    }

    @Override
    public int getCount() {
        return initializers.size();
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return titles.get(position);
    }
}
Alex Miragall
fuente
-5

Sigue probando este código,

public class MYFragmentPAdp extends FragmentPagerAdapter {

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

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

     @Override
     public Fragment getItem(int position) {
         if (position == 0)
             Fragment fragment = new Fragment1();
         else (position == 1)
             Fragment fragment = new Fragment2();
         return fragment;
     }
}
Najib Ahmed Puthawala
fuente
Najib, como expliqué en mi respuesta a continuación, getItem () está creando un nuevo fragmento en lugar de devolver los existentes, ya que uno podría esperar obtener el nombre de pila y no crear . Vea mi solución en la misma publicación.
Ismar Slomic
Fragmento fragmento = new YourCustomFragmentClass (); escriba aquí compruebe esto.
Najib Ahmed Puthawala
Todavía no entiendo cómo esto cambia el hecho de que está creando un nuevo fragmento en lugar de obtener uno existente ..
Ismar Slomic
Todavía inicializa y regresa solo para su fragmento personalizado, como Fragment fragment = new YourFragment (); devolver fragmento;
Najib Ahmed Puthawala