Verständnis von Fragmenten Backstack

Also, es gibt einige ähnliche Fragen, aber ich habe nicht ein einziges gefunden, das dieses Problem löst. Die offizielle Android-Dokumentation scheint intuitiv zu sein, aber wenn ich eine App mit einem komplizierteren Workflow implementiere, wird der Fragment-Backstack unordentlich und seltsame Sachen beginnen. Ich habe ein Skelett für einfache Apps entwickelt, mit der Idee einer einzigen Aktivität, auf die von seinen Fragmenten zugegriffen werden kann, um andere Fragmente zu starten. So habe ich es gemacht:

1- Ich lasse meine Hauptaktivität eine Schnittstelle namens "FragmentDelegate"

  • Konfiguriere Eclipse, um den signierten Keystore zu verwenden
  • Android Ist es möglich, eine Karte in einer XML-Datei zu definieren?
  • Was ist der Unterschied zwischen Bitmap und Drawable in Android?
  • SetType für einen EditText?
  • Programmieren Sie den Wert einer Farbresource, die aus der API-Antwort erhalten wurde, programmgesteuert
  • Service nicht verfügbar beim Aufruf von geoCoder.getFromLocation ()
  • public interface FragmentDelegate { public void startFragment(CCFragment fragment, boolean addToBackStack); } 

    2- Die Implementierung der startFrargment-Methode:

     @Override public void startFragment(CCFragment fragment, boolean addToBackStack) { FragmentManager fragmentManager = getSupportFragmentManager(); fragment.setFragmentDelegate(this); FragmentTransaction fragmentTransaction = fragmentManager .beginTransaction(); fragmentTransaction.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left, R.anim.slide_in_left, R.anim.slide_out_right); fragmentTransaction.replace(CONTENT_VIEW_ID, fragment, "callerFragmentClassName"); if (addToBackStack) fragmentTransaction.addToBackStack("callerFragmentClassName"); fragmentTransaction.commitAllowingStateLoss(); } 

    Das kühle Ding darüber ist, kann ich von jedem Fragment anrufen:

     mFragmentDelegate.startFragment(aNewFragment, addToBackStack); 

    OK jetzt den folgenden Fall-Szenario denken:

    Ich beginne meine Tätigkeit mit einem anfänglichen Fragment, lass uns Fragment A sagen. Aus Fragment A rufe ich die Kamera-Aktivität für ein Ergebnis an. Wenn das Ergebnis eintrifft, beginne ich Fragment B (Hinzufügen von A zum Backstack). Von BI starten Fragment C ohne Hinzufügen von B zum Backstack. Also haben wir das im backstack:

    [A] [C]

    Wenn ich die rückseitige Taste drücke, komme ich zurück zu A. Wenn ich den Vorgang wiederhole, wird der Backstack durcheinander gebracht und wenn ich zurück drücke, braucht es mich immer wieder zum C-Fragment …

    Ich weiß, das ist schwer zu verstehen (und schwieriger für mich zu erklären, weil Englisch ist nicht meine Muttersprache), aber wenn jemand mir erklären könnte, wie die Android-Fragmente Backstack wirklich funktionieren, oder bieten eine Art Skelett für eine App, wäre großartig.

  • Padding Bars bleiben beim Scrollen GridView
  • So stellen Sie Image-Ressource auf ImageView mit DataBinding ein
  • Encoding und Muxing Video mit MediaCodec und MediaMuxer
  • Warten Sie Unitl ListView's smoothScrollToPosition () beendet
  • Android und Facebook: Wie bekomme ich ein Bild von angemeldeten Benutzer
  • Wie man zwischen den Aktivitäten zieht
  • 4 Solutions collect form web for “Verständnis von Fragmenten Backstack”

    Erläuterung:

    Wenn der FragmentManager gespeicherte FragmentTransactions zurücksendet (zB der Benutzer auf die Schaltfläche "Zurück" klicken oder eine Pop-Methode aufgerufen hat), führt er das Gegenteil von der Aktion aus, die in der gespeicherten FragmentTransaction gespeichert ist. Sie können den genauen Code hier sehen , es ist ziemlich einfach.

    In Ihrem Fall ist die gespeicherte Operationstyp 'ersetzen', also das Zurücksetzen, dh das Entfernen aller hinzugefügten Fragment-Instanzen und das erneute Hinzufügen der entfernten. Also wenn du einen Fragmentstapel wie folgt hast:

    [A] [B]

    FragmentManager weiß, das muss die [B] Fragment-Instanz entfernen und die [A] bei einer Pop-Operation hinzufügen. Das Problem ist, dass du [B] mit [C] ersetzt hast:

    [A] [C]

    Leider weiß der gespeicherte Fragment BackStack-Eintrag nicht über [C]. Während eines Pop-Betriebes wird der FragmentManager [A] neu hinzufügen, wird nicht [B] finden, also tut es nichts dagegen und verlässt [C] wo es ist.

    Lösung

    Eine mögliche Lösung für dieses Problem ist die Verwendung von Kinderfragmenten. Fragment-A ist ein Top-Level-Fragment, aber Fragment-B und Fragment-C sind Kinderfragmente eines WrapperFragments.

    Grundsätzlich, wenn du zu Fragment-B navigierst, ersetzst du Fragment-A mit dem WrapperFragment in einer gespeicherten Transaktion:

    [A] [[B]]

    Danach, wenn der Benutzer zu Fragment-C navigiert, ersetzen Sie nur die [B] des WrapperFragments mit [C]:

    [A] [[C]]

    Wenn der Benutzer die Schaltfläche "Zurück" drückt, werden wir korrekt zurück zu Fragment-A:

    [EIN]

    Demo

    Ich habe ein GitHub-Projekt zusammengestellt , um diese Technik zu demonstrieren.

    Ich kann nicht herausfinden, wie Sie mit knallenden C-Fragmenten immer wieder ohne ganzes Bild von dem, was Sie getan haben, aber hier, was Sie falsch über Backstack:

    • BackStack Eintrag spart tatsächlich den aktuellen Zustand des ganzen FragmentManager , nicht nur einzelnes Fragment. Dh, wenn Sie mehrere Operationen mit mehreren Fragmenten in einer einzigen Transaktion durchführen und addToBackStack() aufrufen, addToBackStack() Sie den Status aller Fragmente in der bevorstehenden Transaktion.

    • Wenn Sie addToBackStack() anrufen, addToBackStack() Sie den nächsten Zustand zum Backstack hinzu, dh eigentlich, wenn Sie addToBackStack() angerufen addToBackStack() , wenn Sie ein Fragment hinzugefügt haben, haben Sie tatsächlich einen Zustand mit B und einen Zustand mit A dahinter – – [A] [B], nicht [A] [C].

    Ich empfehle Ihnen, diesen Code zu benutzen und versuchen Sie alles mit Debugger Blick auf einen Zustand von FragmentManager Objekt:

      int count = fragmentManager.getBackStackEntryCount(); fragmentTransaction.addToBackStack(String.valueOf(count)); 

    Auf diese Weise kannst du verfolgen, was in deiner App wirklich los ist.

    Zuerst erinnern Sie sich:

      .replace() = .remove().add() 

    Einige mögliche Lösungen

      public void onBackPressed(){ // here you have to remove your last fragment. super.onBackPressed(); } 

    ///////////////////////////////////////////////// ///////////////////////////////////////////

     @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { if (getSupportFragmentManager().getBackStackEntryCount() == 0) { this.finish(); return false; } else { getSupportFragmentManager().popBackStack(); removeCurrentFragment(); return false; } } return super.onKeyDown(keyCode, event); } public void removeCurrentFragment() { FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); Fragment currentFrag = getSupportFragmentManager().findFragmentById(R.id.detailFragment); if (currentFrag != null) transaction.remove(currentFrag); transaction.commit(); } 

    ///////////////////////////////////////////////// ////////////////////////////////////

    Für weitere Informationen über Backstack von Fragmenten Check Here and Here

    Dies mag nicht als eine Lösung, aber ich denke, es ist besser, wenn Sie nicht verwenden Fragmente in Situationen wie diese. Zuerst nur eine Aktivität und das Ersetzen von Fragmenten auf Nachfrage scheint wie eine tolle Idee, aber wenn Sie versuchen, Ihre Anwendung auf diese Weise Dinge werden chaotisch zu bauen. (Ich bin dort gewesen und ich spreche aus Erfahrung). Managing BackStack selbst ist nur eines der Probleme. Wie Sie weiter gehen Sie am Ende mit einer Aktivität mit so vielen auf verwandten Code in ihm, die nicht cool ist überhaupt!

    Ich schlage vor, Sie erstellen eine Aktivität für jedes Fragment, das Sie haben und legen Sie einfach Ihr Fragment in sie. Ihre Aktivitäten können in manchen Fällen noch mehrere Fragmente haben (sagen wir, Tabletten oder Landschaftsmodus) und eine in einem anderen Fall (wie Portrait-Modus). Aber du musst keine Ersatzmethode mehr verwenden.

    Aktivitäten können Elternaktivität haben, damit das BackStack-Problem in bestmöglicher Weise wie viele andere Probleme gelöst wird. Dies ist nur ein Vorschlag, der auf Erfahrung basiert, die ich mit Fragmenten hatte. Tu, was du am besten denkst

    Das Android ist ein Google Android Fan-Website, Alles ├╝ber Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.