Fragmento onResume () y onPause () no se llama en backstack

Tengo múltiples fragmentos dentro de una actividad. En un botón, haga clic en Comenzaré un nuevo fragmento y lo agregaré al backstack. Naturalmente, esperaba que se onPause() método onPause() del Fragmento actual y onResume() del nuevo Fragmento. 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, fue,

  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 atrás, HomeFragment aparece y se ve LoginFragment , y se onPause() de HomeFragment y onResume() de LoginFragment .

Lo que obtengo es,

  1. Cuando se hace clic en el botón, HomeFragment reemplaza correctamente a LoginFragment , onResume () de HomeFragment se llama, pero onPause () de LoginFragment nunca se llama.
  2. Cuando se presiona de nuevo, HomeFragment aparece correctamente para revelar LoginFragment , se llama a onPause () de HomeFragment , pero onResume () de LoginFragment nunca se llama.

¿Es este el comportamiento normal? ¿Por qué onResume() de LoginFragment no se llama cuando presiono el botón Atrás?

    Los fragmentos onResume() o onPause() se onPause() solo cuando se onResume() las actividades onResume() o onPause() . Están estrechamente relacionados con la Activity .

    Lea la sección Manejando el Fragmento del Ciclo de Vida de este artículo .

    • Como ha utilizado ft2.replace() , se llama al método FragmentTransaction.remove() y se Loginfragment el Loginfragment . Consulte esto . Entonces se onStop() de LoginFragment lugar de onPause() . (Como el nuevo fragmento reemplaza completamente al anterior).
    • Pero como también ha utilizado ft2.addtobackstack() , el estado del Loginfragment de Loginfragment de Loginfragment se guardará como un paquete y cuando haga clic en el botón HomeFragment de HomeFragment , se onViewStateRestored() seguido de onStart() de LoginFragment . Por lo tanto, eventualmente onResume() no se llamará.

    Si realmente quieres reemplazar el fragmento dentro de otro fragmento, debes usar Fragmentos nesteds .

    En tu código debes reemplazar

     final FragmentManager mFragmentmanager = getFragmentManager(); 

    con

     final FragmentManager mFragmentmanager = getChildFragmentManager(); 

    Aquí está mi versión más robusta de la respuesta de Gor (el uso de fragments.size () no es confiable debido a que el tamaño no se disminuye después de que se hace saltar el fragmento)

     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 fragments = fm.getFragments(); if (fragments != null && fragments.size()>0) { for (Fragment f: fragments) { if (f != null && !f.isHidden()) { return f; } } } } return null; } 

    Tengo un código muy similar al suyo 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 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(); } } 

    Usted simple no puede agregar un fragmento a un fragmento. Esto debe suceder en FragmentActivity. Supongo que está creando LoginFragment en una FragmentActivity, por lo que para que esto funcione debe agregar el HomeFragment a través de FragmentActivity cuando se cierra el inicio de sesión.

    El punto general es que necesita una clase FragmentActivity desde donde agrega cada Fragment al FragmentManager. No es posible hacer esto dentro de una clase Fragment.

    Si agrega el fragmento en XML, no puede intercambiarlos dinámicamente. Lo que ocurre es que son demasiado, por lo que los eventos no se disparan como uno esperaría. El problema está documentado en esta pregunta. FragmenManager replace hace overlay

    Convierta middle_fragment en FrameLayout y cárguelo de la siguiente manera y sus eventos se activarán.

     getFragmentManager().beginTransation(). add(R.id.middle_fragment, new MiddleFragment()).commit(); 
     getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() { @Override public void onBackStackChanged() { List 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

    Lo que hago en fragmento de niño:

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

    Y luego anular onResume en ParentFragment

    Siempre se debe incrustar un fragmento en una actividad y el ciclo de vida del fragmento se ve directamente afectado por el ciclo de vida de la actividad del host. Por ejemplo, cuando la actividad está en pausa, también lo son todos los fragmentos, y cuando se destruye la actividad, también lo hacen todos los fragmentos

    Puedes probar esto,

    Paso 1: anule el método Tabselected en su 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(); } 

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

     public void onDestroyView(){ super.onDestroyView } 

    para el mismo propósito …

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

    1- Para ambos fragmentos, cree un nuevo padre primario abstracto.
    2- Agregue un método abstracto personalizado que ambos deberían implementar.
    3- Llamar desde la instancia actual antes de reemplazar con la segunda.

    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 tiene ViewPager con fragmentos, ViewPager 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 Entonces una necesidad en onResume en algunos casos desaparecerá.

    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