2012-02-23 19 views
13

Tengo un fragmento que tiene su propio estado (botones seleccionados, etc.). Ese estado se pierde en una rotación de pantalla.¿Por qué no se llaman mis fragmentos onSaveInstanceState()?

La actividad que contiene el fragmento tiene un diseño de retrato en/res/layout/y un diseño de paisaje casi idéntico en/res/layout-land /. Ambos diseños incluyen el fragmento de este modo:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"> 
    <fragment 
     android:id="@+id/testFragment" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     class="au.com.x.y.TestFragment" /> 
...</LinearLayout> 

La clase fragmento He estado probando con es:

public class TestFragment extends android.support.v4.app.Fragment { 
    private static final String TAG = "TestFragment"; 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     Log.i(TAG, "onCreate(): " + 
       (savedInstanceState != null ? "NOT NULL" : "NULL")); 
    } 
    public void onActivityCreated(Bundle savedInstanceState) { 
     super.onActivityCreated(savedInstanceState); 
     Log.i(TAG, "onActivityCreated(): " + 
       (savedInstanceState != null ? "NOT NULL" : "NULL")); 
    } 
    public void onSaveInstanceState(Bundle state) { 
     super.onSaveInstanceState(state); 
     Log.i(TAG, "onSaveInstanceState()"); 
     state.putString("saved_thing", "some_value"); 
    } 
    public View onCreateView(
     LayoutInflater inflater, 
     ViewGroup container, 
     Bundle b) { ... } 
} 

Tenga en cuenta que estoy usando el paquete pre-3.0 para fragmentos, trajo a través de ActionBarSherlock.

LogCat me da:

BEFORE SCREEN ROTATION (PORTRAIT): 
02-23 11:45:58.015: I/TestFragment(22629): onCreate(): NULL 
02-23 11:45:58.015: I/TestFragment(22629): onCreateView() 
02-23 11:45:58.035: I/TestFragment(22629): onActivityCreated(): NULL 
AFTER SCREEN ROTATION (LANDSCAPE): 
02-23 11:46:00.615: I/TestFragment(22629): onCreate(): NULL 
02-23 11:46:00.615: I/TestFragment(22629): onCreateView() 
02-23 11:46:00.635: I/TestFragment(22629): onActivityCreated(): NULL 

Como se puede ver, onSaveInstanceState() Nunca se llama, y ​​el fragmento siempre obtiene un nulo savedInstanceState, tanto en onCreate() y onActivityCreated().

He intentado myFragment.setRetainInstance(true) en mis actividades onCreate(), pero eso no ha cambiado nada.

Mi onSaveInstanceState() tiene una @Override, así que sé que no es algo estúpido como un error tipográfico.

He observado uno de los ejemplos de ActionBarSherlock (com.actionbarsherlock.sample.shakespeare) y los fragmentos tienen sus métodos onSaveInstanceState() llamados correctamente. Por lo que puedo decir, ese ejemplo está escrito exactamente cómo mi código es — fragmentos incluidos a través de un diseño y un layout-land XML. Incluso he creado esa muestra usando exactamente la misma versión de ActionBarSherlock que mi proyecto principal, y guardar el estado de la instancia funciona bien para ese ejemplo.

¿Cómo retengo mi estado de fragmentos en rotaciones de pantalla? ¿Por qué no se llama al onSaveInstanceState()?

+0

try y @Override 'onPause()'/'onResume()'. –

+1

La orden llamada en rotación es onPause(), onDestroy(), onCreate(), onCreateView(), onActivityCreated(), onResume(). SavedInstanceState sigue siendo siempre nulo y onSaveInstanceState() nunca se llama. Estoy bastante seguro de que no debería necesitar llamar explícitamente a SaveInstanceState() en cualquier lugar. – George

+0

¿Tiene algo que ver el problema con el fragmento al que se hace referencia en dos lugares diferentes (diseño vertical frente a diseño horizontal)? Tal vez eso indica a Android que estos son dos fragmentos diferentes que no deberían compartir estado. – George

Respuesta

23

Puede conservar myFragment.setRetainInstance(true) para retener el estado, pero lo hace 'automáticamente', es decir, conserva los valores asignados a los miembros de su clase y NO usa onSaveInstanceState (y por lo tanto, savedInstanceState siempre es nulo).

Asegúrese de que el FragmentActivity que aloja este fragmento no anula onSaveInstanceState o cuando lo hace debe llamar al super.onSaveInstanceState(Bundle).

+4

Arg, ¡así de simple! No estaba llamando 'super.onSaveInstanceState()' en mi actividad. Gracias a montones por la respuesta Eric, me estaba arrancando el pelo ... – George

0

Si el fragmento necesita un recurso de disposición diferente al girar, setRetainInstance(true) no se puede utilizar. Este page muestra el ciclo de vida del fragmento con setRetainInstance(true).

idea original es el uso onSaveInstanceState() para conservar todos los datos de los miembros, al igual que una actividad normal. Sin embargo, por algún motivo, no se llama a onSaveInstanceState(). Pero FragmentActivity es correcto, como sugirió @Eric Kok). La mejor solución que encontré es usar Argumentos de Fragment.

Ver el solution por Fyodor Volchyok, es simple. Simplemente trabaje como si fuera outState en onSaveInstanceState() y savedInstanceState en onViewCreated().

Cuestiones relacionadas