2013-06-22 14 views
8

Ich habe eine Aktivität, mit einem Fragment ‚Liste‘ bekam, die auf der auf einer seiner Elemente klicken, wird selbst Fragment zu einem ‚Inhalt‘ ersetzen. Wenn der Benutzer die Zurück-Schaltfläche verwendet, wird er erneut zum Fragment "Liste" gebracht.
Das Problem ist, dass das Fragment in seinem Standardzustand ist, egal, was ich versuche, Daten zu beharren.Wie Fragmentdaten nach Backstack Transaktionen bestehen?

Fakten:

  1. beiden Fragmente werden erzeugt durch public static TheFragment newInstance(Bundle args), setArguments(args) und Bundle args = getArguments()
  2. beiden Fragmente auf dem gleiche Niveau sind, das ein FrameLayout von der übergeordneten Aktivität direkt innen ist (das heißt, nicht verschachtelt Fragmente)
  3. ich will nicht setRetainInstance nennen, weil meine Tätigkeit eine Master/Detail-Fluss, das ein 2 Bereich Layout auf größeren Bildschirme hat. 7 "-Tabletts haben 1 Fenster im Hochformat und 2 Fenster im Querformat. Wenn ich die Fragmentinstanz 'list' behalte, wird es (denke ich) Dinge mit Bildschirmdrehungen verkomplizieren
  4. wenn der Benutzer auf ein Element in der 'Liste' klickt Fragment, das ‚Inhalt‘ Fragment wird durch FragmentTransaction#replace(int, Fragment, String) angezeigt, mit der gleichen ID, aber einem anderen Tag
  5. ich onSaveInstanceState(Bundle) hatte außer Kraft setzen, aber das ist nicht immer vom Framework aufgerufen, wie per the doc: „Es gibt viele Situationen, in denen Ein Fragment kann größtenteils abgerissen werden (z. B. wenn es auf dem Backstack platziert wird und keine Benutzeroberfläche angezeigt wird), aber sein Status wird nicht gespeichert, bis seine besitzende Aktivität seinen Status tatsächlich speichern muss. "
  6. ich die Support-Bibliothek

Vom Punkt 5 oben mit, ich denke, dass Low-End-Geräte, die Speicher nach einem Fragment Transaktion wiederherstellen müssen Fragment#onSaveInstanceState(Bundle) nennen. Auf meinen Testgeräten (Galaxy Nexus und Nexus 7) ruft das Framework diese Methode jedoch nicht auf. Das ist also keine gültige Option.

Also, wie kann ich einige Fragmentdaten behalten? das an Fragment#onCreate, Fragment#onActivityCreated usw. übergebene Bündel ist immer null.

Daher kann ich keinen Unterschied machen von einem brandneuen Fragment Start zu einem Back-Stack-Restore.

Hinweis: mögliche related/duplicate question

+0

Im Moment habe ich nur die Option 'isFromBackStack = getActivity(). GetSupportFragmentManager(). GetBackStackEntryCount()> 0'. Ich hätte gerne etwas saubereres, das fühlt sich für mich wie ein Hack an. Außerdem erhalte ich kein "Bündel" von der vorherigen Fragmentinstanz. –

Antwort

8

Dies scheint nicht richtig, aber hier ist, wie ich tun endete:

public class MyActivity extends FragmentActivity { 
    private Bundle mMainFragmentArgs; 

    public void saveMainFragmentState(Bundle args) { 
     mMainFragmentArgs = args; 
    } 

    public Bundle getSavedMainFragmentState() { 
     return mMainFragmentArgs; 
    } 

    // ... 
} 

Und im Haupt Fragment:

public class MainFragment extends Fragment { 
    @Override 
    public void onActivityCreated(final Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     Bundle args = ((MyActivity) getActivity()).getSavedMainFragmentState(); 

     if (args != null) { 
      // Restore from backstack 
     } else if (savedInstanceState != null) { 
      // Restore from saved instance state 
     } else { 
      // Create from fragment arguments 
      args = getArguments(); 
     } 

     // ... 
    } 

    // ... 

    @Override 
    public void onDestroyView() { 
     super.onDestroyView(); 
     Bundle args = new Bundle(); 
     saveInstance(args); 
     ((MyActivity) getActivity()).saveMainFragmentState(args); 
    } 

    @Override 
    public void onSaveInstanceState(Bundle outState) { 
     super.onSaveInstanceState(outState); 
     saveInstance(outState); 
    } 

    private void saveInstance(Bundle data) { 
     // put data into bundle 
    } 
} 

Es funktioniert!

  • wenn von Backstack zurück, verwendet das Fragment, das die gespeicherten Parameter in onDestroyView
  • aus einem anderen app/Prozess, wenn Back/aus dem Speicher wird das Fragment aus den zum ersten Mal erstellt onSaveInstanceState
  • wieder hergestellt, wenn , das Fragment verwendet die in setArguments

eingestellten Parameter Alle Ereignisse sind abgedeckt, und die aktuellsten Informationen werden immer gespeichert.

Es ist eigentlich komplizierter, es ist interface -based, der Hörer ist un/registriert von onAttach/onDetach. Aber die Prinzipien sind die gleichen.

+0

Wow. Ich lerne gerade android, also vermute ich, dass mir etwas fehlt. Vielleicht sollte ich ein Buch lesen. Ich konnte keine Daten über die Lebensdauer meines Fragments erhalten. Aber das macht den Trick. Danke – terary

+1

Anstatt den Status in onDestroyView für den Backstack-Fall zu speichern, können Sie saveFragmentInstanceState() von FragmentManager verwenden, bevor Sie es entfernen/ersetzen. Dies ruft onSaveInstanceState() auf. Auf diese Weise können Sie den Statuspersistenzcode an einem einzigen Ort beibehalten. –

+0

Ich habe einen ähnlichen Ansatz, wo ich die Liste speichern muss, die zuvor geladen wurde, wenn das "Fragment" ersetzt wird. Weißt du, ob dies Speicherprobleme verursachen könnte? – jlively