2012-08-27 12 views
6

Meine Android-Anwendung hat eine ActionBar, die ändert, die Fragment belegt eine bestimmte FrameLayout. Ich versuche, onSaveInstanceState zu verwenden, um den Status eines Fragments zu speichern, wenn die Registerkarte geändert wird, damit es in onCreateView wiederhergestellt werden kann. Das Problem ist, onSaveInstanceState wird nie aufgerufen. Die Fragment's onDestroyView und onCreateView Methoden werden aufgerufen, aber die Bundle, die an onCreateView geliefert wird, bleibt null.Trennen eines Fragments, das onSaveInstanceState nicht auslöst()

Kann jemand mir bitte erklären, wenn onSaveInstanceState tatsächlich aufgerufen wird, wie ich sicher, kann sie aufgerufen wird, wenn Tabs, oder die beste Praxis zum Speichern und Wiederherstellen des Zustands eines Fragment schaltet, wenn er abgenommen und wieder angebracht?

Fragment:

@Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
     Bundle savedInstanceState) { 
    View view = inflater.inflate(R.layout.event_log, container, false); 

    // Retrieve saved state 
    if (savedInstanceState != null){ 
     System.out.println("log retrieved"); 
    } else { 
     System.out.println("log null"); 
    } 

    return view; 
} 

@Override 
public void onSaveInstanceState(Bundle outState) { 
    System.out.println("log saved"); 
    super.onSaveInstanceState(outState); 
    // more code 
} 

Aktivität:

/** 
* Detach the current Fragment, because another one is being attached. 
*/ 
@Override 
public void onTabUnselected(Tab tab, FragmentTransaction ft) { 
    if (tab.getText().equals(getString(R.string.tab_events))){ 
     if (frEventLog != null) { 
      ft.detach(frEventLog); 
    } 
} 
+0

Mögliche Kopie http://stackoverflow.com/questions/8503629/fragments-onsaveinstancestate-never-called – DeeV

+0

was ist frEventLog? –

Antwort

8

Fragment#onSaveInstanceState nur aufgerufen, wenn die Activity die Fragment Hosting zerstört und es gibt eine Chance, dass Sie wieder auf die gleiche Aktivität kommen kann und die Fragment wird noch zu der FragmentManager hinzugefügt. Der häufigste Fall wäre die Bildschirmdrehung.

Ich denke, Ihre Fragment wird auch setRetainInstance(true) in onCreate zum Beispiel tun müssen. Bin mir über diesen Punkt allerdings nicht ganz sicher.

Sie sollten diese Methode auch aufrufen, wenn Sie beispielsweise die Home-Taste drücken. Das wird die Aktivität zerstören, aber Sie können zum Beispiel mit der Aufgabenliste zurückgehen.

Wenn Sie nur detach() das Fragment alles, was Sie tun müssen, um es zurück zu bekommen, ist es, die FragmentManager dafür zu fragen.

Es gibt zwei Beispiele, die Sie sollten auf einen Blick:

ActionBar FragmentTabs und TabHost FragmentTabs

Das TabHost Beispiel verwendet

ft.add(containerId, fragment, tag); 
// later 
fragment = mActivity.getSupportFragmentManager().findFragmentByTag(tag); 

die Instanzen zu finden, bisher Fragment s hinzugefügt, funktioniert, bis Sie remove() a Fragment


Betreffend onCreateView/onDestroyView: Das wird aufgerufen, sobald ein Fragment losgelöst wird, weil das nächste Mal, wenn Sie es anhängen, ein neues View erstellen muss. Beachten Sie, dass Fragment#onDetached() nicht aufgerufen wird, wenn Sie das Fragment detach(), da es immer noch an die Activity angeschlossen ist. Es wird nur von der View-Hierarchie gelöst.


Es ist ein weiteres schönes Beispiel dafür, wie Fragment Zustand zu halten/wie Fragmente verwenden Zustand in Android Ausbildung zu behalten - Caching Bitmaps.

Das Beispiel fehlt eine kritische Linie aber:

public static RetainFragment findOrCreateRetainFragment(FragmentManager fm) { 
    RetainFragment fragment = (RetainFragment) fm.findFragmentByTag(TAG); 
    if (fragment == null) { 
     fragment = new RetainFragment(); 
     fm.beginTransaction().add(fragment, TAG).commit(); // << add this 
    } 
    return fragment; 
} 
+0

Vielen Dank für Ihre Antwort. Ich hatte den Eindruck, dass die Verwendung von setRetainInstance (true) eher speicherintensiv wäre, da dies bedeuten würde, die Tabs zu speichern anstatt sie zu zerstören und neu zu erstellen, aber ich werde es versuchen. Muss ich meine Fragmente über den FragmentManager ergattern oder kann ich in einem Feld auf sie verweisen? – Dan

+0

Sie benötigen keine Referenz. FragmentManager enthält Verweise darauf, Sie können jedoch einen hinzufügen, wenn Sie keine Speicherlecks hinzufügen. Die Speicherintensität hängt davon ab, wie viel du in deinen Fragmenten verwendest, das kann nahe bei 0 liegen, wenn du es richtig machst. – zapl

+0

Ich denke, ich habe das jetzt mit Hilfe deines ersten Beispiels sortiert. Mein Problem war tatsächlich, dass ich etwas Code in der onActivityCreated() Methode des Fragments hatte, der es im Wesentlichen zurücksetzte, als ich nicht erkannte, dass diese Methode mehr als einmal ausgeführt würde. – Dan

Verwandte Themen