He encontrado muchas instancias de una pregunta similar sobre SO, pero desafortunadamente ninguna respuesta cumple con mis requisitos.
Tengo diferentes diseños para retrato y paisaje y estoy usando back stack, lo que me impide usar setRetainState()
y trucos usando rutinas de cambio de configuración.
Muestro cierta información al usuario en TextViews, que no se guardan en el controlador predeterminado. Al escribir mi solicitud únicamente con Actividades, lo siguiente funcionó bien:
TextView vstup;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.whatever);
vstup = (TextView)findViewById(R.id.whatever);
/* (...) */
}
@Override
public void onSaveInstanceState(Bundle state) {
super.onSaveInstanceState(state);
state.putCharSequence(App.VSTUP, vstup.getText());
}
@Override
public void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);
vstup.setText(state.getCharSequence(App.VSTUP));
}
Con Fragment
s, esto funciona solo en situaciones muy específicas. Específicamente, lo que se rompe horriblemente es reemplazar un fragmento, colocarlo en la pila posterior y luego girar la pantalla mientras se muestra el nuevo fragmento. Por lo que entendí, el antiguo fragmento no recibe una llamada onSaveInstanceState()
cuando se reemplaza, pero permanece vinculado de alguna manera al Activity
y este método se llama más tarde cuando View
ya no existe, por lo que busca cualquiera de mis TextView
resultados en a NullPointerException
.
Además, descubrí que mantener la referencia a mi TextViews
no es una buena idea con Fragment
s, incluso si estaba bien con Activity
s. En ese caso, en onSaveInstanceState()
realidad guarda el estado, pero el problema vuelve a aparecer si giro la pantalla dos veces cuando el fragmento está oculto, ya onCreateView()
que no se llama en la nueva instancia.
Pensé en salvar el estado en el onDestroyView()
en algún Bundle
elemento de miembro de la clase de tipo (en realidad es más datos, no sólo uno TextView
) y el ahorro que en onSaveInstanceState()
pero hay otros inconvenientes. Principalmente, si el fragmento se muestra actualmente, el orden de invocar las dos funciones se invierte, por lo que necesitaría tener en cuenta dos situaciones diferentes. ¡Debe haber una solución más limpia y correcta!
fuente
Respuestas:
Para guardar correctamente el estado de la instancia
Fragment
, debe hacer lo siguiente:1. En el fragmento, guarde el estado de instancia anulando
onSaveInstanceState()
y restaurando enonActivityCreated()
:2. Y un punto importante , en la actividad, debe guardar la instancia del fragmento
onSaveInstanceState()
y restaurarlaonCreate()
.Espero que esto ayude.
fuente
Esta es la forma en que estoy usando en este momento ... es muy complicado, pero al menos maneja todas las situaciones posibles. En caso de que alguien esté interesado.
Alternativamente , siempre es posible mantener los datos mostrados en
View
s pasivos en variables y usar losView
s solo para mostrarlos, manteniendo las dos cosas sincronizadas. Sin embargo, no considero que la última parte esté muy limpia.fuente
A
yB
, dondeA
está actualmente en la pila yB
es visible, entonces pierde el estado deA
(lo invisible uno) si gira la pantalla dos veces . El problema es queonCreateView()
no se llama solo en este escenarioonCreate()
. Entonces, más tarde,onSaveInstanceState()
no hay vistas para salvar el estado. Uno tendría que almacenar y luego guardar el estado pasadoonCreate()
.App.VSTUP
yApp.STAV
ambas son etiquetas de cadena que representan los objetos que intentan obtener. Ejemplo:savedState = savedInstanceState.getBundle(savedGamePlayString);
osavedState.getDouble("averageTime")
En la última biblioteca de soporte, ninguna de las soluciones discutidas aquí es necesaria. Puedes jugar con tus
Activity
fragmentos como quieras usando elFragmentTransaction
. Solo asegúrese de que sus fragmentos puedan identificarse con una identificación o etiqueta.Los fragmentos se restaurarán automáticamente siempre que no intentes recrearlos en cada llamada a
onCreate()
. En su lugar, debe verificar sisavedInstanceState
no es nulo y encontrar las referencias antiguas a los fragmentos creados en este caso.Aquí hay un ejemplo:
Sin embargo, tenga en cuenta que actualmente hay un error al restaurar el estado oculto de un fragmento. Si está ocultando fragmentos en su actividad, deberá restaurar este estado manualmente en este caso.
fuente
FragmentPagerAdapter
oFragmentStatePagerAdapter
. Si observa el código deFragmentStatePagerAdapter
, por ejemplo, verá que elrestoreState()
método restaura los fragmentos delFragmentManager
parámetro que pasó al crear el adaptador.Solo quiero dar la solución que se me ocurrió que maneja todos los casos presentados en esta publicación que obtuve de Vasek y devconsole. Esta solución también maneja el caso especial cuando el teléfono se gira más de una vez mientras los fragmentos no son visibles.
Aquí es donde guardo el paquete para su uso posterior ya que onCreate y onSaveInstanceState son las únicas llamadas que se realizan cuando el fragmento no es visible
Dado que destroyView no se llama en la situación de rotación especial, podemos estar seguros de que si crea el estado, deberíamos usarlo.
Esta parte sería la misma.
Ahora aquí está la parte difícil. En mi método onActivityCreated, ejemplifico la variable "myObject", pero la rotación ocurre en onActivity y onCreateView no reciben llamadas. Por lo tanto, myObject será nulo en esta situación cuando la orientación gire más de una vez. Lo soluciono reutilizando el mismo paquete que se guardó en onCreate que el paquete saliente.
Ahora, donde quiera restaurar el estado, simplemente use el paquete savedState
fuente
Gracias a DroidT , hice esto:
Me doy cuenta de que si el Fragment no se ejecuta en onCreateView (), su vista no se instancia. Entonces, si el fragmento en la pila posterior no creó sus vistas, guardo el último estado almacenado, de lo contrario, construyo mi propio paquete con los datos que quiero guardar / restaurar.
1) Amplíe esta clase:
2) En tu Fragmento, debes tener esto:
3) Por ejemplo, puede llamar a hasSavedState en onActivityCreated:
fuente
fuente