Esto se hace mediante la implementación View#onSaveInstanceStatey View#onRestoreInstanceStatey extendiendo la View.BaseSavedStateclase.
public class CustomView extends View {
private int stateToSave;
...
@Override
public Parcelable onSaveInstanceState() {
//begin boilerplate code that allows parent classes to save state
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
//end
ss.stateToSave = this.stateToSave;
return ss;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
//begin boilerplate code so parent classes can restore state
if(!(state instanceof SavedState)) {
super.onRestoreInstanceState(state);
return;
}
SavedState ss = (SavedState)state;
super.onRestoreInstanceState(ss.getSuperState());
//end
this.stateToSave = ss.stateToSave;
}
static class SavedState extends BaseSavedState {
int stateToSave;
SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
this.stateToSave = in.readInt();
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeInt(this.stateToSave);
}
//required field that makes Parcelables from a Parcel
public static final Parcelable.Creator<SavedState> CREATOR =
new Parcelable.Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
}
El trabajo se divide entre la vista y la clase SavedState de la vista. Debes hacer todo el trabajo de lectura y escritura desde y hacia Parcella SavedStateclase. Luego, su clase View puede hacer el trabajo de extraer los miembros del estado y hacer el trabajo necesario para que la clase vuelva a un estado válido.
Notas: View#onSavedInstanceStatey se View#onRestoreInstanceStateles llama automáticamente si View#getIddevuelve un valor> = 0. Esto sucede cuando le da una identificación en xml o llama setIdmanualmente. De lo contrario, usted tiene que llamar View#onSaveInstanceStatey escribir el parcelable regresó a la parcela que se obtiene en Activity#onSaveInstanceStateguardar el estado y posteriormente leerlo y pasarlo a View#onRestoreInstanceStatepartir Activity#onRestoreInstanceState.
Otro ejemplo simple de esto es el CompoundButton
onSaveInstanceState()yonRestoreInstanceState()debería serprotected(como su superclase), nopublic. No hay razón para exponerlos ...BaseSaveStatepara una clase que extiende RecyclerView, porParcel﹕ Class not found when unmarshalling: android.support.v7.widget.RecyclerView$SavedState java.lang.ClassNotFoundException: android.support.v7.widget.RecyclerView$SavedStatelo que debe hacer la corrección de errores que está escrita aquí: github.com/ksoichiro/Android-ObservableScrollView/commit/… (usando el ClassLoader de RecyclerView.class para cargar el súper estado)Creo que esta es una versión mucho más simple.
Bundlees un tipo incorporado que implementaParcelablefuente
onRestoreInstanceStatese llamaría con un paquete si seonSaveInstanceStatedevuelve un paquete?OnRestoreInstancees heredado No podemos cambiar el encabezado.Parcelablees solo una interfaz,Bundlees una implementación para eso.Viewestado base no es unBundle. Por supuesto, eso es cierto en este momento, pero usted confía en este hecho de implementación actual que no se garantiza que sea cierto.Aquí hay otra variante que utiliza una combinación de los dos métodos anteriores. Combinando la velocidad y la corrección de
Parcelablecon la simplicidad de unBundle:fuente
Statepaquete. Por favor, eche un vistazo a: charlesharley.com/2012/programming/…Las respuestas aquí ya son geniales, pero no necesariamente funcionan para grupos de vista personalizados. Para que todas las Vistas personalizadas conserven su estado, debe anular
onSaveInstanceState()yonRestoreInstanceState(Parcelable state)en cada clase. También debe asegurarse de que todos tengan identificadores únicos, ya sea que estén inflados desde xml o agregados mediante programación.Lo que se me ocurrió fue notablemente como la respuesta de Kobor42, pero el error se mantuvo porque estaba agregando las Vistas a un Grupo de Vistas personalizado mediante programación y no asignando identificadores únicos.
El enlace compartido por mato funcionará, pero significa que ninguna de las Vistas individuales gestiona su propio estado: todo el estado se guarda en los métodos ViewGroup.
El problema es que cuando se agregan múltiples de estos ViewGroups a un diseño, los identificadores de sus elementos del xml ya no son únicos (si está definido en xml). En tiempo de ejecución, puede llamar al método estático
View.generateViewId()para obtener una identificación única para una vista. Esto solo está disponible en API 17.Aquí está mi código del ViewGroup (es abstracto, y mOriginalValue es una variable de tipo):
fuente
Tuve el problema de que onRestoreInstanceState restauró todas mis vistas personalizadas con el estado de la última vista. Lo resolví agregando estos dos métodos a mi vista personalizada:
fuente
En lugar de usar
onSaveInstanceStateyonRestoreInstanceState, también puede usar aViewModel. Extienda su modelo de datosViewModely luego puede usarloViewModelProviderspara obtener la misma instancia de su modelo cada vez que se recrea la Actividad:Para usar
ViewModelProviders, agregue lo siguiente adependenciesenapp/build.gradle:Tenga en cuenta que su
MyActivityextiende enFragmentActivitylugar de solo extenderActivity.Puede leer más sobre ViewModels aquí:
fuente
ViewModeles especialmente útil si tiene grandes conjuntos de datos para retener durante un cambio de estado, como una rotación de pantalla. Prefiero usar el enViewModellugar de escribirloApplicationporque tiene un alcance claro, y puedo tener múltiples actividades de la misma aplicación comportándose correctamente.Descubrí que esta respuesta estaba causando algunos bloqueos en las versiones de Android 9 y 10. Creo que es un buen enfoque, pero cuando estaba buscando un código de Android descubrí que le faltaba un constructor. La respuesta es bastante antigua, por lo que en ese momento probablemente no haya sido necesaria. Cuando agregué el constructor faltante y lo llamé desde el creador, se solucionó el bloqueo.
Así que aquí está el código editado:
fuente
Para aumentar otras respuestas: si tiene varias vistas compuestas personalizadas con la misma ID y todas están siendo restauradas con el estado de la última vista en un cambio de configuración, todo lo que necesita hacer es decirle a la vista que solo envíe eventos de guardar / restaurar a sí mismo anulando un par de métodos.
Para una explicación de lo que está sucediendo y por qué esto funciona, vea esta publicación de blog . Básicamente, cada vista compuesta comparte las ID de vista de los niños de su vista compuesta y la restauración del estado se confunde. Al enviar solo el estado para la vista compuesta en sí, evitamos que sus hijos reciban mensajes mixtos de otras vistas compuestas.
fuente