android-activity onsaveinstancestate example - Guardar el estado de la actividad de Android utilizando Guardar estado de instancia





13 Answers

savedInstanceState es solo para guardar el estado asociado con una instancia actual de una actividad, por ejemplo, información de navegación o selección actual, de modo que si Android destruye y recrea una actividad, puede regresar como estaba antes. Consulte la documentación para onCreate y onSaveInstanceState

Para un estado más duradero, considere usar una base de datos SQLite, un archivo o preferencias. Ver Ahorro de estado persistente .

fragment savedinstancestate una

He estado trabajando en la plataforma de Android SDK, y no está nada claro cómo guardar el estado de una aplicación. Entonces, dado este pequeño cambio de herramientas del ejemplo 'Hola, Android':

package com.android.hello;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class HelloAndroid extends Activity {

  private TextView mTextView = null;

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mTextView = new TextView(this);

    if (savedInstanceState == null) {
       mTextView.setText("Welcome to HelloAndroid!");
    } else {
       mTextView.setText("Welcome back.");
    }

    setContentView(mTextView);
  }
}

Pensé que sería suficiente para el caso más simple, pero siempre responde con el primer mensaje, sin importar cómo me aleje de la aplicación.

Estoy seguro de que la solución es tan simple como anular onPause o algo así, pero he estado hurgando en la documentación durante 30 minutos aproximadamente y no he encontrado nada obvio.




Mi colega escribió un artículo que explica el estado de la aplicación en dispositivos Android, que incluye explicaciones sobre el ciclo de vida de la actividad y la información del estado, cómo almacenar la información del estado, y cómo guardar en State Bundle y SharedPreferences y puede consultar aquí .

El artículo cubre tres enfoques:

Almacene datos de control de UI / variable locales para el tiempo de vida de la aplicación (es decir, temporalmente) utilizando el paquete de estado de instancia

[Code sample – Store State in State Bundle]
@Override
public void onSaveInstanceState(Bundle savedInstanceState) 
{
  // Store UI state to the savedInstanceState.
  // This bundle will be passed to onCreate on next call.  EditText txtName = (EditText)findViewById(R.id.txtName);
  String strName = txtName.getText().toString();

  EditText txtEmail = (EditText)findViewById(R.id.txtEmail);
  String strEmail = txtEmail.getText().toString();

  CheckBox chkTandC = (CheckBox)findViewById(R.id.chkTandC);
  boolean blnTandC = chkTandC.isChecked();

  savedInstanceState.putString(“Name”, strName);
  savedInstanceState.putString(“Email”, strEmail);
  savedInstanceState.putBoolean(“TandC”, blnTandC);

  super.onSaveInstanceState(savedInstanceState);
}

Almacene datos de control de UI / variable locales entre instancias de la aplicación (es decir, de forma permanente) utilizando Preferencias Compartidas

[Code sample – Store State in SharedPreferences]
@Override
protected void onPause() 
{
  super.onPause();

  // Store values between instances here
  SharedPreferences preferences = getPreferences(MODE_PRIVATE);
  SharedPreferences.Editor editor = preferences.edit();  // Put the values from the UI
  EditText txtName = (EditText)findViewById(R.id.txtName);
  String strName = txtName.getText().toString();

  EditText txtEmail = (EditText)findViewById(R.id.txtEmail);
  String strEmail = txtEmail.getText().toString();

  CheckBox chkTandC = (CheckBox)findViewById(R.id.chkTandC);
  boolean blnTandC = chkTandC.isChecked();

  editor.putString(“Name”, strName); // value to store
  editor.putString(“Email”, strEmail); // value to store
  editor.putBoolean(“TandC”, blnTandC); // value to store    
  // Commit to storage
  editor.commit();
}

Mantener vivas las instancias de objetos en la memoria entre las actividades dentro del tiempo de vida de la aplicación utilizando la instancia retenida sin configuración

[Code sample – store object instance]
private cMyClassType moInstanceOfAClass;// Store the instance of an object
@Override
public Object onRetainNonConfigurationInstance() 
{
  if (moInstanceOfAClass != null) // Check that the object exists
      return(moInstanceOfAClass);
  return super.onRetainNonConfigurationInstance();
}



Se llama a onSaveInstanceState cuando el sistema necesita memoria y mata una aplicación. No se llama cuando el usuario simplemente cierra la aplicación. Así que creo que el estado de la aplicación también debería guardarse en onPause Debería guardarse en un almacenamiento persistente como Preferences o Sqlite




El estado de ahorro es, en el mejor de los casos, un gran problema en lo que a mí respecta. Si necesita guardar datos persistentes, solo use una SQLite datos SQLite . Android lo hace tan fácil.

Algo como esto:

import java.util.Date;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class dataHelper {

    private static final String DATABASE_NAME = "autoMate.db";
    private static final int DATABASE_VERSION = 1;

    private Context context;
    private SQLiteDatabase db;
    private OpenHelper oh ;

    public dataHelper(Context context) {
        this.context = context;
        this.oh = new OpenHelper(this.context);
        this.db = oh.getWritableDatabase();
    }

    public void close()
    {
        db.close();
        oh.close();
        db = null;
        oh = null;
        SQLiteDatabase.releaseMemory();
    }


    public void setCode(String codeName, Object codeValue, String codeDataType)
    {
        Cursor codeRow = db.rawQuery("SELECT * FROM code WHERE codeName = '"+  codeName + "'", null);
        String cv = "" ;

        if (codeDataType.toLowerCase().trim().equals("long") == true)
        {
            cv = String.valueOf(codeValue);
        }
        else if (codeDataType.toLowerCase().trim().equals("int") == true)
        {
            cv = String.valueOf(codeValue);
        }
        else if (codeDataType.toLowerCase().trim().equals("date") == true)
        {
            cv = String.valueOf(((Date)codeValue).getTime());
        }
        else if (codeDataType.toLowerCase().trim().equals("boolean") == true)
        {
            String.valueOf(codeValue);
        }
        else
        {
            cv = String.valueOf(codeValue);
        }

        if(codeRow.getCount() > 0) //exists-- update
        {
            db.execSQL("update code set codeValue = '" + cv +
                "' where codeName = '" + codeName + "'");
        }
        else // does not exist, insert
        {
            db.execSQL("INSERT INTO code (codeName, codeValue, codeDataType) VALUES(" +
                    "'" + codeName + "'," +
                    "'" + cv + "'," +
                    "'" + codeDataType + "')" );
        }
    }

    public Object getCode(String codeName, Object defaultValue)
    {
        //Check to see if it already exists
        String codeValue = "";
        String codeDataType = "";
        boolean found = false;
        Cursor codeRow  = db.rawQuery("SELECT * FROM code WHERE codeName = '"+  codeName + "'", null);
        if (codeRow.moveToFirst())
        {
            codeValue = codeRow.getString(codeRow.getColumnIndex("codeValue"));
            codeDataType = codeRow.getString(codeRow.getColumnIndex("codeDataType"));
            found = true;
        }

        if (found == false)
        {
            return defaultValue;
        }
        else if (codeDataType.toLowerCase().trim().equals("long") == true)
        {
            if (codeValue.equals("") == true)
            {
                return (long)0;
            }
            return Long.parseLong(codeValue);
        }
        else if (codeDataType.toLowerCase().trim().equals("int") == true)
        {
            if (codeValue.equals("") == true)
            {
                return (int)0;
            }
            return Integer.parseInt(codeValue);
        }
        else if (codeDataType.toLowerCase().trim().equals("date") == true)
        {
            if (codeValue.equals("") == true)
            {
                return null;
            }
            return new Date(Long.parseLong(codeValue));
        }
        else if (codeDataType.toLowerCase().trim().equals("boolean") == true)
        {
            if (codeValue.equals("") == true)
            {
                return false;
            }
            return Boolean.parseBoolean(codeValue);
        }
        else
        {
            return (String)codeValue;
        }
    }


    private static class OpenHelper extends SQLiteOpenHelper {

        OpenHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL("CREATE TABLE IF  NOT EXISTS code" +
            "(id INTEGER PRIMARY KEY, codeName TEXT, codeValue TEXT, codeDataType TEXT)");
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        }
    }
}

Una simple llamada después de eso

dataHelper dh = new dataHelper(getBaseContext());
String status = (String) dh.getCode("appState", "safetyDisabled");
Date serviceStart = (Date) dh.getCode("serviceStartTime", null);
dh.close();
dh = null;



Recrear una actividad

Hay algunos escenarios en los que su actividad se destruye debido al comportamiento normal de la aplicación, como cuando el usuario presiona el botón Atrás o su actividad señala su propia destrucción al llamar finish() . El sistema también puede destruir su actividad si se detiene actualmente y no se ha utilizado durante mucho tiempo o si la actividad en primer plano requiere más recursos, por lo que el sistema debe cerrar los procesos en segundo plano para recuperar la memoria.

Cuando su activity se destruye porque el usuario presiona Atrás o la activity termina por sí misma, el concepto del sistema de esa instancia de Activity desaparece para siempre porque el comportamiento indica que la actividad ya no es necesaria. Sin embargo, si el sistema destruye la actividad debido a las restricciones del sistema (en lugar del comportamiento normal de la aplicación), aunque la instancia de Actividad real ya no existe, el sistema recuerda que existió de tal manera que si el usuario navega hacia ella, el sistema crea una nueva instancia de la actividad que utiliza un conjunto de datos guardados que describe el estado de la actividad cuando se destroyed . Los datos guardados que el sistema utiliza para restaurar el estado anterior se denominan "estado de instancia" y son una colección de pares de clave-valor almacenados en un objeto Bundle.

Para guardar datos adicionales sobre el estado de la actividad, debe anular el método de devolución de llamada onSaveInstanceState (). El sistema llama a este método cuando el usuario abandona su actividad y le pasa el objeto Bundle que se guardará en caso de que su actividad se destruya inesperadamente. Si el sistema debe volver a crear la instancia de actividad más adelante, pasa el mismo objeto Bundle a los onRestoreInstanceState() y onCreate() .

A medida que el sistema comienza a detener su actividad, invoca onSaveInstanceState() (1) para que pueda especificar datos de estado adicionales que desee guardar en caso de que se deba recrear la instancia de la actividad. Si la actividad se destruye y se debe volver a crear la misma instancia, el sistema pasa los datos de estado definidos en (1) tanto al método onCreate() (2) como al método onRestoreInstanceState() (3).

Guarda tu estado de Activity

A medida que su actividad comienza a detenerse, el sistema llama a Guardar Estado de estado de onSaveInstanceState() para que su actividad pueda guardar información de estado con una colección de pares clave-valor. La implementación predeterminada de este método guarda la información sobre el estado de la jerarquía de vista de la actividad, como el texto en un widget EditText o la posición de desplazamiento de un ListView .

Para guardar información de estado adicional para su actividad, debe implementar onSaveInstanceState() y agregar pares clave-valor al objeto Bundle. Por ejemplo:

  static final String STATE_SCORE = "playerScore";
  static final String STATE_LEVEL = "playerLevel";

  @Override
  public void onSaveInstanceState(Bundle savedInstanceState) {
  // Save the user's current game state
  savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
  savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);

  // Always call the superclass so it can save the view hierarchy state
  super.onSaveInstanceState(savedInstanceState);
}

Precaución: Siempre llame a la implementación de superclase de onSaveInstanceState() para que la implementación predeterminada pueda guardar el estado de la jerarquía de vistas.

Restaura tu estado de Activity

Cuando su actividad se vuelve a crear después de haber sido destruida anteriormente, puede recuperar su estado guardado del paquete que el sistema pasa su actividad. Tanto los métodos de devolución de llamada onCreate() como onRestoreInstanceState() reciben el mismo Bundle que contiene la información del estado de la instancia.

Debido a que se llama al método onCreate() si el sistema está creando una nueva instancia de su actividad o recreando una anterior, debe verificar si el estado del paquete es nulo antes de intentar leerlo. Si es nulo, entonces el sistema está creando una nueva instancia de la actividad, en lugar de restaurar una anterior que fue destruida.

Por ejemplo, aquí es cómo puede restaurar algunos datos de estado en onCreate() :

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState); // Always call the superclass first

 // Check whether we're recreating a previously destroyed instance
 if (savedInstanceState != null) {
    // Restore value of members from saved state
    mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
    mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
 } else {
    // Probably initialize members with default values for a new instance
 }

 }

En lugar de restaurar el estado durante onCreate() , puede elegir implementar onRestoreInstanceState() , que el sistema llama después del método onStart() . El sistema llama onRestoreInstanceState() solo si hay un estado guardado para restaurar, por lo que no es necesario verificar si el paquete es nulo:

  public void onRestoreInstanceState(Bundle savedInstanceState) {
  // Always call the superclass so it can restore the view hierarchy
  super.onRestoreInstanceState(savedInstanceState);

  // Restore state members from saved instance
  mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
  mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}



Realmente decir onSaveInstancecallen cuando la actividad pasa a segundo plano

Cita de la documentación: "el método onSaveInstanceState(Bundle)se llama antes de colocar la actividad en ese estado de fondo"




Para ayudar a reducir la plantilla, uso lo siguiente interfacey classpara leer / escribir en un Bundleestado de instancia de guardado.

Primero, cree una interfaz que se usará para anotar sus variables de instancia:

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({
        ElementType.FIELD
})
public @interface SaveInstance {

}

Luego, cree una clase donde se usará la reflexión para guardar valores en el paquete:

import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;

import java.io.Serializable;
import java.lang.reflect.Field;

/**
 * Save and load fields to/from a {@link Bundle}. All fields should be annotated with {@link
 * SaveInstance}.</p>
 */
public class Icicle {

    private static final String TAG = "Icicle";

    /**
     * Find all fields with the {@link SaveInstance} annotation and add them to the {@link Bundle}.
     *
     * @param outState
     *         The bundle from {@link Activity#onSaveInstanceState(Bundle)} or {@link
     *         Fragment#onSaveInstanceState(Bundle)}
     * @param classInstance
     *         The object to access the fields which have the {@link SaveInstance} annotation.
     * @see #load(Bundle, Object)
     */
    public static void save(Bundle outState, Object classInstance) {
        save(outState, classInstance, classInstance.getClass());
    }

    /**
     * Find all fields with the {@link SaveInstance} annotation and add them to the {@link Bundle}.
     *
     * @param outState
     *         The bundle from {@link Activity#onSaveInstanceState(Bundle)} or {@link
     *         Fragment#onSaveInstanceState(Bundle)}
     * @param classInstance
     *         The object to access the fields which have the {@link SaveInstance} annotation.
     * @param baseClass
     *         Base class, used to get all superclasses of the instance.
     * @see #load(Bundle, Object, Class)
     */
    public static void save(Bundle outState, Object classInstance, Class<?> baseClass) {
        if (outState == null) {
            return;
        }
        Class<?> clazz = classInstance.getClass();
        while (baseClass.isAssignableFrom(clazz)) {
            String className = clazz.getName();
            for (Field field : clazz.getDeclaredFields()) {
                if (field.isAnnotationPresent(SaveInstance.class)) {
                    field.setAccessible(true);
                    String key = className + "#" + field.getName();
                    try {
                        Object value = field.get(classInstance);
                        if (value instanceof Parcelable) {
                            outState.putParcelable(key, (Parcelable) value);
                        } else if (value instanceof Serializable) {
                            outState.putSerializable(key, (Serializable) value);
                        }
                    } catch (Throwable t) {
                        Log.d(TAG, "The field '" + key + "' was not added to the bundle");
                    }
                }
            }
            clazz = clazz.getSuperclass();
        }
    }

    /**
     * Load all saved fields that have the {@link SaveInstance} annotation.
     *
     * @param savedInstanceState
     *         The saved-instance {@link Bundle} from an {@link Activity} or {@link Fragment}.
     * @param classInstance
     *         The object to access the fields which have the {@link SaveInstance} annotation.
     * @see #save(Bundle, Object)
     */
    public static void load(Bundle savedInstanceState, Object classInstance) {
        load(savedInstanceState, classInstance, classInstance.getClass());
    }

    /**
     * Load all saved fields that have the {@link SaveInstance} annotation.
     *
     * @param savedInstanceState
     *         The saved-instance {@link Bundle} from an {@link Activity} or {@link Fragment}.
     * @param classInstance
     *         The object to access the fields which have the {@link SaveInstance} annotation.
     * @param baseClass
     *         Base class, used to get all superclasses of the instance.
     * @see #save(Bundle, Object, Class)
     */
    public static void load(Bundle savedInstanceState, Object classInstance, Class<?> baseClass) {
        if (savedInstanceState == null) {
            return;
        }
        Class<?> clazz = classInstance.getClass();
        while (baseClass.isAssignableFrom(clazz)) {
            String className = clazz.getName();
            for (Field field : clazz.getDeclaredFields()) {
                if (field.isAnnotationPresent(SaveInstance.class)) {
                    String key = className + "#" + field.getName();
                    field.setAccessible(true);
                    try {
                        Object fieldVal = savedInstanceState.get(key);
                        if (fieldVal != null) {
                            field.set(classInstance, fieldVal);
                        }
                    } catch (Throwable t) {
                        Log.d(TAG, "The field '" + key + "' was not retrieved from the bundle");
                    }
                }
            }
            clazz = clazz.getSuperclass();
        }
    }

}

Ejemplo de uso:

public class MainActivity extends Activity {

    @SaveInstance
    private String foo;

    @SaveInstance
    private int bar;

    @SaveInstance
    private Intent baz;

    @SaveInstance
    private boolean qux;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Icicle.load(savedInstanceState, this);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Icicle.save(outState, this);
    }

}

Nota: este código fue adaptado de un proyecto de biblioteca llamado AndroidAutowire que está licenciado bajo la licencia MIT .




Los métodos onSaveInstanceState(bundle)y onRestoreInstanceState(bundle)son útiles para la persistencia de datos simplemente mientras se gira la pantalla (cambio de orientación).
Ni siquiera son buenas, mientras que el cambio entre aplicaciones (ya que el onSaveInstanceState()se llama método, pero onCreate(bundle)y onRestoreInstanceState(bundle)no se invoca de nuevo.
Para un uso más persistencia preferencias compartidas. Leer este artículo




Aunque la respuesta aceptada es correcta, existe un método más rápido y sencillo para guardar el estado de la actividad en Android mediante una biblioteca llamada Icepick . Icepick es un procesador de anotaciones que se encarga de todo el código de repetición utilizado para guardar y restaurar el estado.

Haciendo algo así con Icepick:

class MainActivity extends Activity {
  @State String username; // These will be automatically saved and restored
  @State String password;
  @State int age;

  @Override public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Icepick.restoreInstanceState(this, savedInstanceState);
  }

  @Override public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    Icepick.saveInstanceState(this, outState);
  }
}

Es lo mismo que hacer esto:

class MainActivity extends Activity {
  String username;
  String password;
  int age;

  @Override
  public void onSaveInstanceState(Bundle savedInstanceState) {
    super.onSaveInstanceState(savedInstanceState);
    savedInstanceState.putString("MyString", username);
    savedInstanceState.putString("MyPassword", password);
    savedInstanceState.putInt("MyAge", age); 
    /* remember you would need to actually initialize these variables before putting it in the
    Bundle */
  }

  @Override
  public void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    username = savedInstanceState.getString("MyString");
    password = savedInstanceState.getString("MyPassword");
    age = savedInstanceState.getInt("MyAge");
  }
}

Icepick trabajará con cualquier objeto que guarde su estado con un Bundle.




Cuando se crea una actividad, se llama al método onCreate ().

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

savedInstanceState es un objeto de la clase Bundle que es nulo por primera vez, pero contiene valores cuando se recrea. Para guardar el estado de la actividad, debe anular onSaveInstanceState ().

   @Override
    protected void onSaveInstanceState(Bundle outState) {
      outState.putString("key","Welcome Back")
        super.onSaveInstanceState(outState);       //save state
    }

ponga sus valores en el objeto del paquete "outState" como outState.putString ("key", "Welcome Back") y guárdelo llamando a super. Cuando se destruye la actividad, se guarda el estado en el objeto Bundle y se puede restaurar después de la recreación en onCreate () o onRestoreInstanceState (). El paquete recibido en onCreate () y onRestoreInstanceState () es el mismo.

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

          //restore activity's state
         if(savedInstanceState!=null){
          String reStoredString=savedInstanceState.getString("key");
            }
    }

o

  //restores activity's saved state
 @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
      String restoredMessage=savedInstanceState.getString("key");
    }



Código Kotlin:

salvar:

override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState.apply {
        putInt("intKey", 1)
        putString("stringKey", "String Value")
        putParcelable("parcelableKey", parcelableObject)
    })
}

y luego en onCreate()oonRestoreInstanceState()

    val restoredInt = savedInstanceState?.getInt("intKey") ?: 1 //default int
    val restoredString = savedInstanceState?.getString("stringKey") ?: "default string"
    val restoredParcelable = savedInstanceState?.getParcelable<ParcelableClass>("parcelableKey") ?: ParcelableClass() //default parcelable

Agrega valores predeterminados si no quieres tener Opcionales




Simple rápido para resolver este problema es usar Icepick

Primero, configura la biblioteca en app/build.gradle

repositories {
  maven {url "https://clojars.org/repo/"}
}
dependencies {
  compile 'frankiesardo:icepick:3.2.0'
  provided 'frankiesardo:icepick-processor:3.2.0'
}

Ahora, veamos este ejemplo a continuación, cómo guardar el estado en la Actividad.

public class ExampleActivity extends Activity {
  @State String username; // This will be automatically saved and restored

  @Override public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Icepick.restoreInstanceState(this, savedInstanceState);
  }

  @Override public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    Icepick.saveInstanceState(this, outState);
  }
}

Funciona para Actividades, Fragmentos o cualquier objeto que necesite serializar su estado en un Bundle (por ejemplo, ViewPresenters de mortero)

Icepick también puede generar el código de estado de instancia para vistas personalizadas:

class CustomView extends View {
  @State int selectedPosition; // This will be automatically saved and restored

  @Override public Parcelable onSaveInstanceState() {
    return Icepick.saveInstanceState(this, super.onSaveInstanceState());
  }

  @Override public void onRestoreInstanceState(Parcelable state) {
    super.onRestoreInstanceState(Icepick.restoreInstanceState(this, state));
  }

  // You can put the calls to Icepick into a BaseCustomView and inherit from it
  // All Views extending this CustomView automatically have state saved/restored
}



Ahora Android proporciona ViewModels para guardar el estado, debe intentar usar eso en lugar de saveInstanceState.




Related