wake-up-neo.com

Das Fragment onResume () & onPause () wird beim Backstack nicht aufgerufen

Ich habe mehrere Fragmente in einer Aktivität. Klicken Sie auf eine Schaltfläche, um ein neues Fragment zu erstellen, und fügen Sie es dem Backstack hinzu. Ich habe natürlich erwartet, dass die onPause() Methode des aktuellen Fragments und onResume() des neuen Fragments aufgerufen wird. Nun, es passiert nicht.

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

Was ich erwartet hatte, war

  1. Wenn Sie auf die Schaltfläche klicken, wird LoginFragment durch HomeFragment, onPause() von LoginFragment und onResume() von HomeFragment abgerufen namens
  2. Wenn Zurück gedrückt wird, wird HomeFragment ausgefahren und LoginFragment wird angezeigt. _ Und onPause() von HomeFragment und onResume() von LoginFragment wird gerufen.

Was ich bekomme ist

  1. Wenn die Schaltfläche angeklickt wird, ersetzt HomeFragment korrekt __.LoginFragment, onResume () von HomeFragment wird aufgerufen, aber onPause () Von LoginFragment wird nie aufgerufen .
  2. Wenn Sie die Taste "Zurück" drücken, wird HomeFragment korrekt angezeigtLoginFragment wird onPause () von HomeFragment aufgerufen, aber onResume () Von LoginFragment wird nie angezeigt namens.

Ist das das normale Verhalten? Warum wird onResume() of LoginFragment nicht aufgerufen, wenn ich die Zurück-Taste drücke.

167
Krishnabhadra

Die Fragmente onResume() oder onPause() werden nur aufgerufen, wenn die Aktivitäten onResume() oder onPause() aufgerufen werden .. .. Sie sind fest mit der Activity gekoppelt.

Lesen Sie den Abschnitt Umgang mit dem Fragment-Lebenszyklus dieses Artikels .

157
Sagar Waghmare
  • Da Sie ft2.replace() verwendet haben, wird die Methode FragmentTransaction.remove() aufgerufen und Loginfragment entfernt. Siehe this . Daher wird onStop() von LoginFragment anstelle von onPause() aufgerufen. (Da das neue Fragment das alte vollständig ersetzt).
  • Da Sie jedoch auch ft2.addtobackstack() verwendet haben, wird der Status von Loginfragment als Bundle gespeichert. Wenn Sie in HomeFragment auf die Schaltfläche "Zurück" klicken, wird onViewStateRestored() gefolgt von aufgerufen onStart() von LoginFragment. Schließlich wird onResume() nicht aufgerufen.
18
Gopal

Wenn Sie das Fragment wirklich in einem anderen Fragment ersetzen möchten, sollten Sie Nested Fragmente verwenden.

In Ihrem Code sollten Sie ersetzen

final FragmentManager mFragmentmanager =  getFragmentManager();

mit

final FragmentManager mFragmentmanager =  getChildFragmentManager();
8
Bersh

Hier ist meine robustere Version von Gors Antwort (die Verwendung von fragments.size () ist unzuverlässig, da die Größe nicht verringert wird, nachdem das Fragment abgelegt wurde)

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

Und die Methode '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;
}
6
aaronmarino
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
            }

        }
    });

seien Sie jedoch vorsichtig, wenn mehr als ein Fragment sichtbar ist

2
Gor

Ich habe einen Code, der Ihrem sehr ähnlich ist, und ob es onPause () und onResume () funktioniert. Beim Ändern des Fragments werden diese Funktionen jeweils aktiviert.

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

}

Log bei Fragmentwechsel:

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

Aktion, wenn ich zurückspringe (in der Aktivität, in der ich das Fragment lade):

@Override
public void onBackPressed() {

    int count = getFragmentManager().getBackStackEntryCount();

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

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

 }
2
PepitoGrillo

Sie können dies versuchen,

Schritt 1: Überschreiben Sie die tabellierte Methode in Ihrer Aktivität

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

Schritt 2: Verwenden Sie statische Methoden, was Sie in Ihrem Fragment wollen.

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

Sie können einfach kann nicht einem Fragment ein Fragment hinzufügen. Dies muss in der FragmentActivity geschehen. Ich gehe davon aus, dass Sie das LoginFragment in einer FragmentActivity erstellen. Damit dies funktioniert, müssen Sie das HomeFragment über die FragmentActivity hinzufügen, wenn die Anmeldung geschlossen wird.

Der allgemeine Punkt ist, dass Sie eine FragmentActivity-Klasse benötigen, von der Sie jedes Fragment zum FragmentManager hinzufügen. Es ist nicht möglich, dies innerhalb einer Fragment-Klasse durchzuführen.

1
Nickolaus

Wenn Sie das Fragment in XML hinzufügen, können Sie sie nicht dynamisch vertauschen. Was passiert, ist sie übermäßig, so dass Ereignisse nicht wie erwartet ausgelöst werden. Das Problem ist in dieser Frage dokumentiert. FragmenManager ersetzt Overlay

Verwandeln Sie middle_fragment in ein FrameLayout und laden Sie es wie unten, und Ihre Ereignisse werden ausgelöst.

getFragmentManager().beginTransation().
    add(R.id.middle_fragment, new MiddleFragment()).commit();
1
Dustin

Was mache ich im Kindfragment:

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

Überschreiben Sie dann onResume auf ParentFragment

1

Ein Fragment muss immer in eine Aktivität eingebettet sein, und der Lebenszyklus des Fragments ist direkt vom Lebenszyklus der Host-Aktivität betroffen. Wenn zum Beispiel die Aktivität angehalten wird, sind alle Fragmente darin, und wenn die Aktivität zerstört wird, sind dies auch alle Fragmente

0
Xar E Ahmer

Die onPause()-Methode funktioniert in der Aktivitätsklasse, die Sie verwenden können:

public void onDestroyView(){
super.onDestroyView    
}

für den gleichen Zweck ..

0

Obwohl mit anderem Code, hatte ich dasselbe Problem wie das OP, da ich es ursprünglich verwendet habe 

fm.beginTransaction()
            .add(R.id.fragment_container_main, fragment)
            .addToBackStack(null)
            .commit();

anstatt

fm.beginTransaction()
                .replace(R.id.fragment_container_main, fragment)
                .addToBackStack(null)
                .commit();

Mit "replace" wird das erste Fragment neu erstellt, wenn Sie vom zweiten Fragment zurückkehren. Daher wird onResume () auch aufgerufen. 

0
Greg Holst

Der Aufruf von ft.replace sollte die onPause (des ersetzten Fragments) und onResume (des ersetzenden Fragments) auslösen.

Ich stelle fest, dass Ihr Code login_fragment auf dem Ausgangsfragment aufbläst und die Ansichten in onCreateView nicht zurückgibt. Wenn dies Tippfehler sind, können Sie dann zeigen, wie diese Fragmente aus Ihrer Aktivität heraus aufgerufen werden?

0
David Refaeli

Basierend auf der Antwort von @Gor schrieb ich ähnlich in Kotlin. Fügen Sie diesen Code in onCreate() einer Aktivität ein. Es funktioniert für ein Fragment sichtbar. Wenn Sie ViewPager mit Fragmenten haben, wird ViewPagers Fragment aufgerufen, nicht ein vorheriges.

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

Nach dem Lesen von https://medium.com/@elye.project/puzzle-fragment-stack-pop-cause-issue-on-toolbar-8b947c5c07c6 habe ich verstanden, dass es in vielen Situationen besser wäre, neue Fragmente anzufügen mit replace, nicht add. In einigen Fällen wird also ein Bedarf in onResume verschwinden.

0
CoolMind

Befolgen Sie die nachstehenden Schritte, und Sie erhalten die erforderliche Antwort

1- Erstellen Sie für beide Fragmente ein neues abstraktes übergeordnetes.
2- Fügen Sie eine benutzerdefinierte abstrakte Methode hinzu, die von beiden implementiert werden soll.
3- Rufen Sie die aktuelle Instanz auf, bevor Sie sie durch die zweite Instanz ersetzen.

0
Mostafa Magdy

Ich benutze in meiner Tätigkeit -KOTLIN

supportFragmentManager.addOnBackStackChangedListener {
                val f = supportFragmentManager.findFragmentById(R.id.fragment_container)

                if (f?.tag == "MyFragment")
                {
                    //doSomething
                }
            }
0
Álvaro Agüero