Fragment onResume () & onPause () n'est pas appelé backstack

j'ai plusieurs fragments dans une activité. Sur un clic de bouton je commence un nouveau fragment, en l'ajoutant à backstack. Je m'attendais naturellement à ce que la méthode onPause() du Fragment courant et onResume() du nouveau Fragment soit appelée. Eh bien, il n'est pas le cas.

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'ai attendu, a été,

  1. quand le bouton est cliqué, LoginFragment est remplacé par HomeFragment , onPause() de LoginFragment , et onResume() de HomeFragment est appelée
  2. lorsque le dos est pressé, HomeFragment est poped out et LoginFragment est vu, et onPause() de HomeFragment et onResume() de LoginFragment est appelée.

Ce que je reçois est,

  1. lorsque le bouton est cliqué, HomeFragment remplace correctement LoginFragment , onResume() de HomeFragment est appelé, mais onPause() de LoginFragment n'est jamais appelé.
  2. Quand le dos appuyé, HomeFragment est correctement popping à révéler LoginFragment , onPause() de HomeFragment est appelée, mais onResume() de LoginFragment ne se fait jamais appeler.

est-ce le comportement normal? Pourquoi onResume() de LoginFragment n'est pas appelé quand j'appuie sur le bouton arrière.

159
demandé sur galvan 2012-07-04 13:23:31

15 réponses

les fragments onResume() ou onPause() ne seront appelés que lorsque les activités onResume() ou onPause() sont appelées. Ils sont étroitement liés au Activity .

lisez la section traitant du cycle de vie des fragments de cet article .

154
répondu Sagar Waghmare 2014-05-22 10:06:17
  • depuis que vous avez utilisé ft2.replace() , FragmentTransaction.remove() la méthode est appelée et le Loginfragment sera supprimée. Se référer à ce . Ainsi onStop() de LoginFragment sera appelé au lieu de onPause() . (Comme le nouveau fragment remplace complètement l'ancien).
  • mais puisque vous avez aussi utilisé ft2.addtobackstack() , l'état du Loginfragment sera sauvé comme un paquet et quand vous cliquez sur le bouton de retour de HomeFragment , onViewStateRestored() sera appelé suivi de onStart() de LoginFragment . Donc finalement onResume() ne sera pas appelé.
18
répondu Gopal 2013-04-27 14:10:38

si vous voulez vraiment remplacer un fragment à l'intérieur d'un autre fragment, vous devez utiliser fragments imbriqués .

dans votre code vous devez remplacer

final FragmentManager mFragmentmanager =  getFragmentManager();

avec

final FragmentManager mFragmentmanager =  getChildFragmentManager();
8
répondu Bersh 2015-12-11 23:46:32

voici ma version plus robuste de la réponse de Gor (en utilisant des fragments.size () n'est pas fiable car la taille n'est pas décrémentée après l'éclatement du 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<Fragment> fragments = fm.getFragments();
        if (fragments != null && fragments.size()>0) {
            for (Fragment f: fragments) {
                if (f != null && !f.isHidden()) {
                    return f;
                }
            }
        }
    }
    return null;
}
5
répondu aaronmarino 2016-11-24 17:41:30

j'ai un code très similaire au vôtre et s'il fonctionne onPause () et onResume (). En changeant le fragment, ces fonctions sont activées respectivement.

Code dans 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");

}

Journal lorsqu'un 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 onreateview:

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 quand je reviens en impulsion (dans l'activité où je charge le fragment):

@Override
public void onBackPressed() {

    int count = getFragmentManager().getBackStackEntryCount();

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

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

 }
2
répondu PepitoGrillo 2017-05-19 20:45:14

simple ne peut pas ajouter un fragment d'un fragment. Cela doit se produire dans L'activité de fragmentation. Je suppose que vous créez le LoginFragment dans une Activitéfragmentaire, donc pour que cela fonctionne, vous devez ajouter le HomeFragment via L'Activitéfragmentaire lorsque le login ferme.

le point général est que vous avez besoin d'une classe de FragmentActivity d'où vous ajoutez chaque Fragment au FragmentManager. C'est impossible pour faire cela à l'intérieur d'une classe de fragments.

1
répondu Nickolaus 2013-10-11 16:38:46

si vous ajoutez le fragment en XML, vous ne pouvez pas l'échanger dynamiquement. Ce qui se passe, c'est qu'ils sont exagérés, donc ils ne tirent pas comme on pourrait s'y attendre. La question est documentée dans cette question. FragmenManager remplacer rend le revêtement

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();
1
répondu Dustin 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
            }

        }
    });

mais faites attention si plus d'un fragment est visible

1
répondu Gor 2016-10-13 13:47:59

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

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

et puis outrepasser onResume sur parents fragment

1
répondu Guillermo De Juan 2017-12-10 09:01:58

un fragment doit toujours être intégré dans une activité et son cycle de vie est directement affecté par le cycle de vie de l'activité hôte. Par exemple, lorsque l'activité est suspendue, ce sont donc tous les fragments, et lorsque l'activité est détruite, ce sont donc tous les fragments

0
répondu Xar E Ahmer 2014-07-16 11:29:20

Vous pouvez essayer ce,

Step1: outrepasser 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: Utilisation de 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();
}
0
répondu Manoj Kumar 2016-01-20 12:25:31

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

public void onDestroyView(){
super.onDestroyView    
}

dans le même but..

0
répondu Vikrant Kaloniya 2017-04-02 19:29:51

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

1-pour les deux fragments, créer un nouveau parent abstrait.

2-Ajouter une méthode abstraite personnalisée qui devrait être implémentée par les deux.

3-L'appeler à partir de l'instance actuelle avant de remplacer par la seconde.

0
répondu Mostafa Magdy 2018-04-09 21:09:33

basé sur la réponse de @Gor j'ai écrit similaire dans Kotlin. Placez ce code dans onCreate() d'une activité. Il fonctionne pour un fragment visible. Si vous avez ViewPager avec des fragments, il appellera ViewPager 's fragment, pas un précédent.

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

après https://medium.com/@elye.project/puzzle-fragment-stack-pop-cause-issue-on-toolbar-8b947c5c07c6 j'ai compris qu'il serait mieux dans de nombreuses situations pour attacher de nouveaux fragments avec replace , pas add . Ainsi, un besoin dans onResume disparaîtra dans certains cas.

0
répondu CoolMind 2018-08-02 12:39:38

lors de la création d'une transaction de fragment, assurez-vous d'ajouter 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 commettre la transaction après l'avoir ajoutée à backstack

-2
répondu Mayur More 2013-03-07 13:26:44