Le fragment onResume () & onPause () n’est pas appelé sur le backstack

J’ai plusieurs fragments à l’intérieur d’une activité. Sur un clic de bouton, je commence un nouveau fragment, en l’ajoutant à backstack. Je m’attendais naturellement à onPause() méthode onPause() du fragment actuel et onResume() du nouveau fragment. Eh bien, ça ne se passe pas.

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

Ce que j’attendais, c’était,

  1. Lorsque l’utilisateur clique sur le bouton, LoginFragment est remplacé par HomeFragment , onPause() de LoginFragment et onResume() de HomeFragment est appelé
  2. Lorsque l’utilisateur appuie sur Retour , HomeFragment est affiché et LoginFragment est visible, et onPause() de HomeFragment et onResume() de LoginFragment sont appelés.

Ce que je reçois, c’est

  1. Lorsque l’utilisateur clique sur le bouton, HomeFragment remplace correctement LoginFragment , on appelle onResume () de HomeFragment , mais onPause () de LoginFragment n’est jamais appelé.
  2. Lorsque vous appuyez en arrière, HomeFragment est correctement affiché pour révéler LoginFragment , onPause () de HomeFragment est appelé, mais onResume () de LoginFragment n’est jamais appelé.

Est-ce le comportement normal? Pourquoi onResume() de LoginFragment n’est pas appelé lorsque j’appuie sur le bouton Retour.

    Related of "Le fragment onResume () & onPause () n’est pas appelé sur le backstack"

    Les fragments onResume() ou onPause() seront appelés uniquement lorsque les activités onResume() ou onPause() sont appelées. Ils sont étroitement liés à l’ Activity .

    Lisez la section Gestion du cycle de vie des fragments de cet article .

    • Comme vous avez utilisé ft2.replace() , la méthode FragmentTransaction.remove() est appelée et le Loginfragment sera supprimé. Reportez-vous à ceci . Donc onStop() de LoginFragment sera appelé au lieu de onPause() . (Comme le nouveau fragment remplace complètement l’ancien).
    • Mais comme vous avez également utilisé ft2.addtobackstack() , l’état du Loginfragment sera enregistré en tant que bundle et lorsque vous cliquez sur le bouton de HomeFragment , onViewStateRestored() sera appelé suivi de onStart() de LoginFragment . Donc, finalement onResume() ne sera pas appelé.

    Si vous voulez vraiment remplacer fragment dans un autre fragment, vous devez utiliser des fragments nesteds .

    Dans votre code, vous devez remplacer

     final FragmentManager mFragmentmanager = getFragmentManager(); 

    avec

     final FragmentManager mFragmentmanager = getChildFragmentManager(); 

    Voici ma version plus robuste de la réponse de Gor (l’utilisation de fragments.size () n’est pas fiable car la taille n’est pas décrémentée après le saut de fragment)

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

    Et la méthode ‘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; } 

    J’ai un code très similaire au vôtre et si ça marche onPause () et onResume (). Lors du changement de fragment, ces fonctions sont activées respectivement.

    Code en fragment:

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

    Connectez-vous lorsque le changement de fragment:

     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 

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

    Action lorsque je rentre (dans l’activité où je charge le fragment):

     @Override public void onBackPressed() { int count = getFragmentManager().getBackStackEntryCount(); if (count == 0) { super.onBackPressed(); } else { getFragmentManager().popBackStack(); } } 

    Vous ne pouvez simplement pas append un fragment à un fragment. Cela doit se produire dans FragmentActivity. Je suppose que vous créez le LoginFragment dans un FragmentActivity, donc pour que cela fonctionne, vous devez append le HomeFragment via FragmentActivity à la fermeture de la connexion.

    Le point général est que vous avez besoin d’une classe FragmentActivity à partir de laquelle vous ajoutez chaque fragment au FragmentManager. Il n’est pas possible de faire cela dans une classe de fragment.

    Si vous ajoutez le fragment en XML, vous ne pouvez pas les échanger dynamicment. Qu’est-ce qui se passe est-ce qu’ils sont trop, alors ils ne tirent pas comme on pourrait s’y attendre. Le problème est documenté dans cette question. FragmenManager replace make overlay

    Transformez middle_fragment en FrameLayout et chargez-le comme ci-dessous et vos événements se déclencheront.

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

    mais faites attention si plus d’un fragment est visible

    Ce que je fais dans le fragment de l’enfant:

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

    Et ensuite remplacer onResume sur ParentFragment

    Un fragment doit toujours être incorporé dans une activité et le cycle de vie du fragment est directement affecté par le cycle de vie de l’activité hôte. Par exemple, lorsque l’activité est en pause, tous les fragments sont présents, et lorsque l’activité est détruite, il en va de même pour tous les fragments.

    Vous pouvez essayer ceci,

    Etape 1: Remplacez la méthode Tabselected dans votre activité

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

    Étape 2: En utilisant la méthode statique, faites ce que vous voulez dans votre fragment,

     public static void fragmentChanged() { Toast.makeText(actvity, "Fragment Changed", Toast.LENGTH_SHORT).show(); } 

    onPause() méthode onPause() fonctionne dans la classe d’activité que vous pouvez utiliser:

     public void onDestroyView(){ super.onDestroyView } 

    dans le même but ..

    Suivez les étapes ci-dessous, et vous obtiendrez la réponse nécessaire

    1- Pour les deux fragments, créez un nouveau parent parent abstrait.
    2- Ajouter une méthode abstraite personnalisée qui doit être mise en œuvre par les deux.
    3- Appelez-le depuis l’instance actuelle avant de le remplacer par le second.

    Sur la base de la réponse de @Gor, j’ai écrit la même chose à Kotlin. Placez ce code dans onCreate() d’une activité. Cela fonctionne pour un fragment visible. Si vous avez ViewPager avec des fragments, il appellera le fragment de ViewPager , pas un précédent.

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

    Après avoir lu https://medium.com/@elye.project/puzzle-fragment-stack-pop-cause-issue-on-toolbar-8b947c5c07c6, j’ai compris qu’il serait préférable, dans de nombreuses situations, d’attacher de nouveaux fragments avec replace , pas add Ainsi, un besoin dans onResume dans certains cas.

    Lors de la création d’une transaction fragmentée, veillez à append le code suivant.

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

    Assurez-vous également de valider la transaction après l’avoir ajoutée au backstack