Evento cuando se completa FragmentTransaction

4 minutos de lectura

¿Es posible tener un evento cuando se completa FragmentTransaction?

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, fragment).commit();

De hecho, uso un cajón para mi aplicación y me gustaría activar invalidateOptionsMenu(); cuando se completa la transacción para cambiar el menú de mi barra de acción.

No necesita esperar a que se complete la transacción del fragmento, puede llamar

getSupportFragmentManager().executePendingTransactions();

después de su llamada a la función commit().

Esto asegurará que la transacción esté completa.

  • Mi problema no es si mi transacción salió bien sino saber cuándo finalizó. De lo contrario, hay un espacio entre la visualización de mi vista y el cambio de la barra de menú de mi acción.

    – lopez.mikhael

    1 de noviembre de 2013 a las 10:16

  • La transacción se completará con fuerza cuando llame a executePendingTransactions… sin embargo, la vista tardará un tiempo en cargarse. Para averiguarlo, use una función estática y llámela desde el onResume de su fragmento.

    – Eldhose M Babu

    1 de noviembre de 2013 a las 12:04


  • Creo que esta es una respuesta válida, incluso si no es un “evento” per se. ejecutarTransaccionesPendientes() bloquear hasta que se complete la transacción, y el siguiente comando posterior se invocará al finalizar la transacción, tal como lo haría un evento, e incluso sin la sobrecarga del detector de eventos.

    – Amir Uval

    7 de mayo de 2014 a las 7:39

  • Esto no es exacto, al agregar un fragmento después del comprometerse y ejecutar transacciones pendientes se devuelve la pila de fragmentos tiene el fragmento agregado, mientras se elimina o reemplaza un Fragmento y después comprometerse y ejecutar transacciones pendientes se llama, el fragmento eliminado todavía está en la pila hasta un momento posterior. Tiene sentido por razones de UX eliminar y destruir el fragmento más tarde, sin embargo, ¡esta no es la forma correcta de obtener un evento de transacción completada!

    – TacB0sS

    7 mayo 2015 a las 18:48


  • No me gustó esta respuesta, pero me di cuenta de que podría usar una solución al poner un evento usando EventBus justo después de la llamada a executePendingTransactions()y hacer que mi fragmento escuche ese evento, y si cumple con los criterios para la eliminación, puede aparecer solo llamando popFragment() en su administrador de fragmentos. (Estaba tratando de poner eso popFragment() código en onResume() si los datos de su modelo no existían, pero estaba dando el IllegalStateException: FragmentManager is already executing transactions error.) Básicamente hice mi propio “Evento” para cuando era una transacción completa.

    – Roca Lee

    09/03/2017 a las 20:20


¡Hola! Prueba esto:

private OnBackStackChangedListener backStackListener =  new OnBackStackChangedListener() {

    @Override
    public void onBackStackChanged() {
        String name = "";
        int position = getSupportFragmentManager().getBackStackEntryCount();
        if(position!=0){
           FragmentManager.BackStackEntry backEntry=getSupportFragmentManager().getBackStackEntryAt(position-1);
           name=backEntry.getName();


        }
        if(position==0){
            mainActionBar();
        }
        else if(name=="someWord"){
            mainActionBar2();
        }
        else{
            mainActionBar3();
        }

    }
};
 getSupportFragmentManager().addOnBackStackChangedListener(backStackListener);

Y en Transacción, agregue una etiqueta a backStack de esta manera:

getSupportFragmentManager().beginTransaction()
                .replace(R.id.main, SomeFragment.newInstance(some argument))
                .addToBackStack("someWord").commit();

  • Esto es válido solo si no está agregando animaciones personalizadas.

    – Papá Akhil

    9 mayo 2015 a las 12:51

  • onBackStackChanged recibe una llamada al inicio de la transición. Esto nunca es válido.

    – Servus7

    14/07/2015 a las 17:43

  • Gracias @Mikelis, estaba buscando mostrar el botón Atrás cuando fuera necesario, addBackStackChangedListener funcionó de maravilla 🙂

    – Sumit

    8 de enero de 2020 a las 15:03

Demasiado tarde, pero esto puede ayudar (poner aquí para que alguien pueda usar):

....
fragmentTransaction.replace(R.id.contentFrame, fragment);
fragmentTransaction.runOnCommit(new Runnable() // be carefull on this call. check documentation!!
{
    @Override
    public void run()
    {
        ... do something...  // this will  run after fragment's on resume. you can check.
    }
});
fragmentTransaction.commit();

¡verifique las restricciones del método runOnCommit()!

  • Requiere API 26, que no siempre está disponible.

    – Stephen M -en huelga-

    27 sep 2019 a las 18:36

  • No requiere API 26 si está utilizando la biblioteca de soporte FragmentTransaction (que debería ser la mayoría). androidx.fragment.app.FragmentTransaction

    – Riot se vuelve guau

    10 de marzo de 2020 a las 22:11


@Override
public void onResume() {
    super.onResume();
    getActivity().invalidateOptionsMenu();
}

Cuando se complete FragmentTransaction, se llamará a los métodos del ciclo de vida del Fragmento, como onResume()

FYI, fragmento puede tiene su propio menú, ver http://developer.android.com/reference/android/app/Fragment.html#setHasOptionsMenu(booleano)

avatar de usuario
marca minto

Puede usar el consejo dado en esta respuesta: ejecute el código que necesita después de que se complete la transacción desde el onAnimationEnd método.

Para que esto funcione, debe configurar una animación en FragmentTransaction usando, por ejemplo

transaction.setCustomAnimations(R.anim.slide_in_left,
                                R.anim.slide_out_right);

avatar de usuario
UriB

Podría considerar usar commitNow() en lugar de commit() y luego puede estar seguro de que la transacción ha finalizado. Por supuesto, es una cuestión de la complejidad de la transacción si debe hacerlo o no.

avatar de usuario
BADER EDDINE QODIA

Creo que respondí a tu pregunta tan tarde, pero podría ayudar a alguien que quiera la misma solución:

ft.getLifecycle().addObserver(new LifecycleEventObserver() {
                 @Override
                 public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
                     if(event.getTargetState() == Lifecycle.State.RESUMED){
                         new Handler().postDelayed(new Runnable() {
                             @Override
                             public void run() {
                                invalidateOptionsMenu();
                             }
                         }, 500);
                     }
                 }
             });

¿Ha sido útil esta solución?