Fragment onResume () & onPause () no se llama en backstack


Tengo múltiples fragmentos dentro de una actividad. Al hacer clic en un botón, estoy comenzando un nuevo fragmento, agregándolo a backstack. Naturalmente esperaba que se llamara al método onPause() del Fragmento actual y onResume() del Fragmento nuevo. Bueno, no está sucediendo.

LoginFragment.java

public class LoginFragment extends Fragment{
  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
      final View view  =   inflater.inflate(R.layout.login_fragment, container, false);
      final FragmentManager mFragmentmanager =  getFragmentManager();

      Button btnHome  = (Button)view.findViewById(R.id.home_btn);
      btnHome.setOnClickListener(new View.OnClickListener() {
        public void onClick(View view){
           HomeFragment fragment    = new HomeFragment();
           FragmentTransaction ft2   =  mFragmentmanager.beginTransaction();
           ft2.setCustomAnimations(R.anim.slide_right, R.anim.slide_out_left
                    , R.anim.slide_left, R.anim.slide_out_right);
           ft2.replace(R.id.middle_fragment, fragment);
           ft2.addToBackStack(""); 
           ft2.commit();    
         }
      });
  }

  @Override
  public void onResume() {
     Log.e("DEBUG", "onResume of LoginFragment");
     super.onResume();
  }

  @Override
  public void onPause() {
    Log.e("DEBUG", "OnPause of loginFragment");
    super.onPause();
  }
}

HomeFragment.java

public class HomeFragment extends Fragment{
  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
     final View view  =   inflater.inflate(R.layout.login_fragment, container, false);
  }

  @Override
  public void onResume() {
     Log.e("DEBUG", "onResume of HomeFragment");
     super.onResume();
  }

  @Override
  public void onPause() {
     Log.e("DEBUG", "OnPause of HomeFragment");
     super.onPause();
  }
}

Lo que esperaba, era, {[10]]}

  1. Cuando se hace clic en el botón, LoginFragment se reemplaza con HomeFragment, onPause() de LoginFragment, y onResume() de HomeFragment se llama
  2. Cuando se presiona back, HomeFragment se abre y LoginFragment se seen, and onPause() of HomeFragment and onResume() of LoginFragment se llama.

Lo que estoy recibiendo es,

  1. Cuando se hace clic en el botón, HomeFragment está reemplazando correctamente LoginFragment , onResume () of HomeFragment se llama, pero onPause() de LoginFragment nunca se llama.
  2. Cuando se presiona hacia atrás, HomeFragment aparece correctamente para revelar LoginFragment , onPause () of HomeFragment se llama, pero onResume() de LoginFragment nunca se llama.

¿Es este el comportamiento normal? ¿Por qué onResume() of LoginFragment no recibe una llamada cuando presiono el botón atrás?

Author: galvan, 2012-07-04

15 answers

Los fragmentos onResume() o onPause() se llama sólo cuando las Actividades onResume() o onPause() es llamado. Están estrechamente acoplados al Activity.

Lea la sección Manejo del Ciclo de vida del fragmento de este artículo.

 154
Author: Sagar Waghmare,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-22 10:06:17
  • Puesto que ha utilizado ft2.replace(), FragmentTransaction.remove() se llama al método y se eliminará Loginfragment. Refiérase a esto . Así que onStop() de LoginFragment se llamará en lugar de onPause(). (Como el nuevo fragmento sustituye por completo el antiguo).
  • Pero puesto que también utilizado ft2.addtobackstack(), el estado de la Loginfragment será guardado como un paquete y al hacer clic en el botón atrás de HomeFragment, onViewStateRestored() será llamado seguido por onStart() de LoginFragment. Así que eventualmente onResume() no será llamado.
 18
Author: Gopal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-27 14:10:38

Si realmente desea reemplazar el fragmento dentro de otro fragmento, debe usar Fragmentos anidados.

En su código debe reemplazar

final FragmentManager mFragmentmanager =  getFragmentManager();

Con

final FragmentManager mFragmentmanager =  getChildFragmentManager();
 8
Author: Bersh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-11 23:46:32

Aquí está mi versión más robusta de la respuesta de Gor (usando fragmentos.size () no es confiable debido a que el tamaño no se decrementa después de que el fragmento se revienta)

getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
            if (getFragmentManager() != null) {

                Fragment topFrag = NavigationHelper.getCurrentTopFragment(getFragmentManager());

                if (topFrag != null) {
                    if (topFrag instanceof YourFragment) {
                        //This fragment is being shown. 
                    } else {
                        //Navigating away from this fragment. 
                    }
                }
            }
        }
    });

Y el método 'getCurrentTopFragment':

public static Fragment getCurrentTopFragment(FragmentManager fm) {
    int stackCount = fm.getBackStackEntryCount();

    if (stackCount > 0) {
        FragmentManager.BackStackEntry backEntry = fm.getBackStackEntryAt(stackCount-1);
        return  fm.findFragmentByTag(backEntry.getName());
    } else {
        List<Fragment> fragments = fm.getFragments();
        if (fragments != null && fragments.size()>0) {
            for (Fragment f: fragments) {
                if (f != null && !f.isHidden()) {
                    return f;
                }
            }
        }
    }
    return null;
}
 5
Author: aaronmarino,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-24 17:41:30

Tengo un código muy similar al tuyo y si funciona onPause () y onResume (). Al cambiar el fragmento, estas funciones se activan respectivamente.

Código en fragmento:

 @Override
public void onResume() {
    super.onResume();
    sensorManager.registerListener(this, proximidad, SensorManager.SENSOR_DELAY_NORMAL);
    sensorManager.registerListener(this, brillo, SensorManager.SENSOR_DELAY_NORMAL);
    Log.e("Frontales","resume");
}

@Override
public void onPause() {
    super.onPause();
    sensorManager.unregisterListener(this);
    Log.e("Frontales","Pause");

}

Registro cuando el cambio de fragmento:

05-19 22:28:54.284 2371-2371/madi.cajaherramientas E/Frontales: resume
05-19 22:28:57.002 2371-2371/madi.cajaherramientas E/Frontales: Pause
05-19 22:28:58.697 2371-2371/madi.cajaherramientas E/Frontales: resume
05-19 22:29:00.840 2371-2371/madi.cajaherramientas E/Frontales: Pause
05-19 22:29:02.248 2371-2371/madi.cajaherramientas E/Frontales: resume
05-19 22:29:03.718 2371-2371/madi.cajaherramientas E/Frontales: Pause

Fragmento onCreateView:

View rootView;
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

    rootView = inflater.inflate(R.layout.activity_proximidad, container, false);
    ButterKnife.bind(this,rootView);
    inflar();
    setTextos();
    return rootView;
}

Acción cuando pulso hacia atrás (en la actividad donde cargo el fragmento):

@Override
public void onBackPressed() {

    int count = getFragmentManager().getBackStackEntryCount();

    if (count == 0) {
        super.onBackPressed();

    } else {
        getFragmentManager().popBackStack();
    }

 }
 2
Author: PepitoGrillo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-19 20:45:14

Simplemente no puede agregar un fragmento a un fragmento. Esto tiene que suceder en el FragmentActivity. Asumo que estás creando el LoginFragment en un FragmentActivity, por lo que para que esto funcione, necesitas agregar el HomeFragment a través de FragmentActivity cuando se cierre el inicio de sesión.

El punto general es que necesita una clase FragmentActivity desde la que agregue cada Fragmento al FragmentManager. No es posible hacer esto dentro de una clase de Fragmento.

 1
Author: Nickolaus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-11 16:38:46

Si agrega el fragmento en XML, no puede intercambiarlo dinámicamente. Lo que sucede es que ellos son demasiado, por lo que los eventos no se disparan como uno esperaría. La cuestión está documentada en esta pregunta. FragmenManager reemplazar hace superposición

Convierte middle_fragment en un FrameLayout, y cárgalo como abajo y tus eventos se activarán.

getFragmentManager().beginTransation().
    add(R.id.middle_fragment, new MiddleFragment()).commit();
 1
Author: Dustin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:26:26
getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
            List<Fragment> fragments = getFragmentManager().getFragments();
            if (fragments.size() > 0 && fragments.get(fragments.size() - 1) instanceof YoureFragment){
                //todo if fragment visible
            } else {
                //todo if fragment invisible
            }

        }
    });

Pero ten cuidado si hay más de un fragmento visible

 1
Author: Gor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-13 13:47:59

Lo que hago en fragmento hijo:

@Override
public void onDetach() {
   super.onDetach();
   ParentFragment pf = (ParentFragment) this.getParentFragment();
   pf.onResume();
}

Y luego sobreescribir onResume en ParentFragment

 1
Author: Guillermo De Juan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-10 09:01:58

Un fragmento siempre debe estar incrustado en una actividad y el ciclo de vida del fragmento se ve directamente afectado por el ciclo de vida de la actividad host. Por ejemplo, cuando la actividad se detiene, también lo son todos los fragmentos en ella, y cuando la actividad se destruye, también lo son todos los fragmentos

 0
Author: Xar E Ahmer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-16 11:29:20

Puedes probar esto,

Paso 1: Anula el método Tabselected en tu actividad

@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
    // When the given tab is selected, switch to the corresponding page in
    // the ViewPager.
    try {
    if(MyEventsFragment!=null && tab.getPosition()==3)
    {
        MyEvents.fragmentChanged();
    }
    }
    catch (Exception e)
    {

    }
    mViewPager.setCurrentItem(tab.getPosition());
}

Paso 2: Usando el método estático haz lo que quieras en tu fragmento,

public static void fragmentChanged()
{
    Toast.makeText(actvity, "Fragment Changed", Toast.LENGTH_SHORT).show();
}
 0
Author: Manoj Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-20 12:25:31

onPause() el método funciona en la clase de actividad que puede usar:

public void onDestroyView(){
super.onDestroyView    
}

Para el mismo propósito..

 0
Author: Vikrant Kaloniya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-02 19:29:51

Siga los pasos a continuación y obtendrá la respuesta necesaria

1 - Para ambos fragmentos, cree un nuevo padre abstracto.
2-Añadir un método abstracto personalizado que debe ser implementado por ambos.
3-Llámelo desde la instancia actual antes de reemplazarlo con la segunda.

 0
Author: Mostafa Magdy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-09 21:09:33

Basado en la respuesta de @Gor Escribí algo similar en Kotlin. Coloque este código en onCreate() de una actividad. Funciona para un fragmento visible. Si tienes ViewPager con fragmentos, llamará al fragmento de ViewPager, no a uno anterior.

supportFragmentManager.addOnBackStackChangedListener {
    supportFragmentManager.fragments.lastOrNull()?.onResume()
}

Después de leer https://medium.com/@elye.project/puzzle-fragment-stack-pop-cause-issue-on-toolbar-8b947c5c07c6 Entendí que sería mejor en muchas situaciones adjuntar nuevos fragmentos con replace, no add. Así que una necesidad en onResume en algunos casos desaparecerán.

 0
Author: CoolMind,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-02 12:39:38

Al crear una transacción de fragmento, asegúrese de agregar el siguiente código.

// Replace whatever is in the fragment_container view with this fragment, 
// and add the transaction to the back stack 
transaction.replace(R.id.fragment_container, newFragment); 
transaction.addToBackStack(null); 

También asegúrese de confirmar la transacción después de agregarla a backstack

 -2
Author: Mayur More,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-07 13:26:44