viernes, 20 de abril de 2012

6.9.6.Android-Guardando la configuración (I)


6.9.6.- Programación en Android – Actividad Configuración – Guardando la configuración.

En un capítulo anterior habíamos visto como utilizar el mecanismo de SharedPreferences para guardar ciertos datos de la aplicación, en este capítulo vamos a aplicar lo aprendido para guardar la configuración del usuario en nuestro archivo de preferencias.

Definiendo los nombres de los campos a guardar

Al comienzo de nuestra aplicación añadimos una variable en el fichero ActividadGlobal.java, :

//Variables para SharedPreferences:
protected static final String PREFERENCIAS_JUEGO = "correctoincorrecto.prefs"; //Nombre del archivo.


Dicha variable es el nombre que tendrá nuestro archivo de SharedPreferences. Ahora debemos añadir varias variables de texto, que serán los campos utilizados en “pares” (nombre+valor) dentro del fichero de preferencias. Dichos campos de momento corresponden a los valores que tenemos para introducir dentro de la actividad de configuración:

protected static final String PREFERENCIAS_JUEGO_NOMBRE = "Nombre"; //Será un string.
protected static final String PREFERENCIAS_JUEGO_EMAIL = "Email"; //Será un string.
protected static final String PREFERENCIAS_JUEGO_CLAVE = "Clave"; //Será un string.
protected static final String PREFERENCIAS_JUEGO_FECHA_NACIMIENTO = "FechaNacimiento";//Será un long.
protected static final String PREFERENCIAS_JUEGO_GENERO = "Genero";//Será un int:0=masc, 1=fem,2=Ns/NC.

Al lado de cada variable se ha puesto como comentario el tipo de campo que se utilizará (string, long, int), ya que a la hora de cargar los datos y guardarlos, debemos de utilizar estos tipos.

Accediendo a los datos

Ahora que tenemos definidos los nombres de los campos que guardaremos, vamos a ver como haremos para guardar los datos.
Primeramente debemos de definir una variable miembro para la clase ActividadConfiguración, esta variable la definimos fuera de cualquier método, para que sea accesible por todos los métodos de la clase:

SharedPreferences mFicheroConfig;

Ahora que tenemos definido el interface, tenemos que inicializarlo, y esto lo hacemos dentro del método onCreate (de ActividadConfiguración.java):

//Creamos el interface para poder acceder al fichero
//con las preferencias: Lo obtenemos.
mFicheroConfig = getSharedPreferences(PREFERENCIAS_JUEGO,
MODE_PRIVATE);

Ya podríamos guardar los datos a través de un SharedPreferences.Editor. Volveremos sobre ello más adelante.

Cargando los datos e inicializando los widgets/views

Con el interface creado, vamos a proceder a cargar los datos existentes del fichero de configuración y a inicializar las vistas de la ActividadConfiguración con los valores que ya existan. Creamos para ello un método: inicializaVistas(),y en dicho método realizaremos las inicializaciones de cada una de las vistas de nuestra actividad. Este método lo llamaremos desde onCreate.

En nuestro método inicializaVistas() realizaremos varias llamadas a métodos auxiliares que se encargaran de cargar los datos e inicializar las vistas individualmente:

private void inicializaVistas()
{
// TODO Cargar los datos en caso de que existan y actualizar las cajas.
//#1 Inicializamos el EditText del Nombre
inicializaNombre();
//#2 Inicializamos el EditText del Email
inicializaEmail();
//#3 Inicializamos el TextView de la clave.
inicializaClave();
//#4 Cargamos los datos para la fecha de nacimiento:
inicializaFecha();
//#5 Cargamos los datos del spinner
inicializaSpinnerGeneros();

//Ahora deberían de estar todas las cajas inicializadas:
if (VALOR_DEBUG) Log.v(LOG_GLOBAL, "Salida de ActividadConfiguracion.InicializaVistas()");
}

inicializaNombre()

En este método inicializaremos el EditText con el nombre del jugador, cargándolo desde las preferencias, en caso de que existan. Veamos el código:

private void inicializaNombre()
{
//#1 Cargamos los datos para el 1er editText (Nombre)
EditText ET_Nombre = (EditText)findViewById(R.id.editText_Nombre);
//Comprobamos que existe el nombre, y en ese caso lo cargamos
// En caso de que no exista se pone a "";
if (mFicheroConfig.contains(PREFERENCIAS_JUEGO_NOMBRE))
{
ET_Nombre.setText(mFicheroConfig.getString(
PREFERENCIAS_JUEGO_NOMBRE, ""));
}
}

En la sentencia if comprobamos si existe la clave (o campo) PREFERENCIAS_JUEGO_NOMBRE, en cuyo caso se procede a cargarlo.

El método setText pone el valor de texto del control EditText.

El método getString devuelve el valor de la cadena asociada al nombre de campo PREFERENCIAS_JUEGO_NOMBRE, y en caso de que no exista pone dicho valor igual a “” (cadena vacía). En caso de que el campo que contenga este nombre no sea de tipo string se genera una excepción de tipo ClassCastException.

Toda vez que el método getString puede inicializar la cadena a un valor por defecto en caso de no existir la clave, podríamos prescindir del if. Pero no está de más por seguridad.
Debemos realizar lo mismo para los otros campos.

inicializaEmail()

Al igual que realizamos con el nombre, hacemos lo mismo con el Email.

private void inicializaEmail()
{
//#2 Cargamos los datos para el 2º editText (Email)
//Igual que en el paso #1
EditText ET_Email = (EditText) findViewById(R.id.editText_Email);
if (mFicheroConfig.contains(PREFERENCIAS_JUEGO_EMAIL))
{
ET_Email.setText(mFicheroConfig.getString(PREFERENCIAS_JUEGO_EMAIL,""));
}
}

No voy a comentar dicho código ya que es idéntico al empleado para el nombre.

inicializaClave()

En este método cargamos la clave en caso de que exista, pero a diferencia de los otros métodos, aquí no mostramos el valor, simplemente mostramos que la clave existe y cambiamos el color de dicho mensaje.

private void inicializaClave()
{
//#3 Cargamos los datos para la Clave.
TextView TV_Clave = (TextView) findViewById(R.id.tV_EstadoClave);
if (mFicheroConfig.contains(PREFERENCIAS_JUEGO_CLAVE))
{
//Ponemos "Hay clave" en la clave, ya que no vamos
// a mostrar la clave.
TV_Clave.setText(res.getString(R.string.str_HayClave));
//Y Cambiamos el color del texto:
TV_Clave.setTextColor(res
.getColor(R.color.color_EditText_Configuracion));
}
else
{
//En caso de que no exista la clave en el fichero:
// Ponemos el string de No hay clave, y el color de error.
TV_Clave.setText(res.getString(R.string.str_NoHayClave));
TV_Clave.setTextColor(res.getColor(R.color.color_Error));
}
}

En este método lo único que tenemos de nuevo es el método setTextColor, que hace que el texto del widget, en este caso un control TextView, tenga el color indicado por el recurso correspondiente.

inicializaFecha()

En este método se carga la fecha de nacimiento del jugador, la fecha la guardamos como un valor de tipo long en el fichero de preferencias, así que ahora lo cargamos como un long y después procedemos a formatearlo.

private void inicializaFecha()
{
TextView TV_Fecha = (TextView) findViewById(R.id.tV_EstadoFecha);
if (mFicheroConfig.contains(PREFERENCIAS_JUEGO_FECHA_NACIMIENTO))
{
//Creamos un Long para albergar el valor, ya que despues lo formatearemos.
Long fecha;
fecha = mFicheroConfig.getLong(PREFERENCIAS_JUEGO_FECHA_NACIMIENTO,0);
//TODO: Añadir un recurso String con el formato de la fecha:
TV_Fecha.setText(DateFormat.format( res.getString(R.string.formatoFecha), fecha));
TV_Fecha.setTextColor(res
.getColor(R.color.color_EditText_Configuracion));
}
else
{
// En caso de no existir la fecha:
TV_Fecha.setText(res.getString(R.string.str_NoHayFecha));
TV_Fecha.setTextColor(res.getColor(R.color.color_Error));
}
}

Aquí utilizamos el método getLong() para cargar un dato de tipo Long.
Antes de mostrar el texto en el TextView, debemos darle formato, lo cual hacemos con método format de la clase DateFormat. Dicho método espera que se le pase un valor string con el formato que se le dará a la fecha, así como el valor de la fecha. Debemos crear un recurso de tipo string llamado formatoFecha, y le pondremos el valor siguiente: dd-MMMM-yyyy.
(El recurso se añade en el fichero values/strings.xml)

inicializaSpinnerGeneros()

Por último inicializamos el Spinner con el género del jugador.

private void inicializaSpinnerGeneros()
{
//Creamos una clase ¿interna? para controlar el callback.
//También podríamos haberla creado anónima, pero así se ve mejor.
//También se puede sacar de aqui y dejarla junto a los métodos.
class spinner_OnItemSelectedListener implements OnItemSelectedListener
{
public void onItemSelected(AdapterView<?> parent, View view,
int posicion, long id)
{
//Se crea un toast para mostrar el elemento seleccionado:
Toast.makeText(parent.getContext(),"Elemento seleccionado:"
+ parent.getItemAtPosition(posicion).toString()
+ " Pos:" + posicion, Toast.LENGTH_LONG).show();
}
public void onNothingSelected(AdapterView<?> parent)
{
//No hacemos nada que no hay nada seleccionado.
}
}
Spinner spin_Generos = (Spinner) findViewById(R.id.spinner_Genero);

/**
* El método createFromResource() crea un nuevo ArrayAdapter que
* enlaza cada elemento en el string array a la apariencia
* inicial que tendrá el Spinner (Que es como aparecerá cada elemento
* en el spinner cuando se seleccione.
* R.array.Generos: Referencia el string-array que habíamos creado.
* android.R.layout.simple_spinner_item: Es un ID que referencia
* un layout para la apariencia estandar del spinner, y está definido por la plataforma.
*
*/
ArrayAdapter<?> adaptador = ArrayAdapter.createFromResource (this,R.array.array_Generos,android.R.layout.simple_spinner_item);
/**
* setDropDownViewResource: Define la apariencia para cada elemento
* cuando se abre el DropDown.
*/
adaptador
.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

/**
* Ahora se asocian los items del adaptador al spinner:
*/
spin_Generos.setAdapter(adaptador);
//Ahora definimos la clase que hará de callback para cuando se seleccione algo:
spin_Generos.setOnItemSelectedListener(new spinner_OnItemSelectedListener());

if (mFicheroConfig.contains(PREFERENCIAS_JUEGO_GENERO))
{
spin_Generos.setSelection(mFicheroConfig.getInt(
PREFERENCIAS_JUEGO_GENERO, 2));
}
else
{
//La selección 2 es la que pone Ns/NC (0=masculino/1=mujer).
spin_Generos.setSelection(2);
}
}

Aquí como tenemos un valor tipo int en el fichero de preferencias, entonces utilizamos el método getInt.

Guardando los valores

Para guardar los valores, debemos de hacer uso del objeto Editor, y realizaremos el guardado en el método onPause(). El spinner podríamos haberlo guardado en su listener cuando se hace una selección, pero al hacerlo aquí tenemos el guardado de los datos todo junto.
Pulsamos con el botón derecho sobre nuestro fichero ActividadConfiguración.java y seleccionamos “Código Fuente->Alterar temporalmente/implementar métodos”, y marcamos la casilla de onPause().

Ahora en el método onPause procedemos a guardar los valores:

protected void onPause()
{
// TODO Auto-generated method stub
super.onPause();

//Procedemos a guardar los datos de las cajas:
//Creamos el objeto Editor para escribir en SharedPreferences:
Editor editorFicheroConf = mFicheroConfig.edit();
//Creamos las referencias de las EditText
EditText ET_Nombre = (EditText) findViewById(R.id.editText_Nombre);
EditText ET_Email = (EditText) findViewById(R.id.editText_Email);
Spinner spin_Generos = (Spinner) findViewById(R.id.spinner_Genero);
//TODO: Faltan los valores para la clave y la fecha de nacimiento

//Cogemos los valores de las vistas:
String strNombre = ET_Nombre.getText().toString();
String strEmail = ET_Email.getText().toString();
int iGenero = spin_Generos.getSelectedItemPosition();
//TODO: Faltan los valores para la clave y la fecha de nacimiento
editorFicheroConf.putString(PREFERENCIAS_JUEGO_NOMBRE, strNombre);
editorFicheroConf.putString(PREFERENCIAS_JUEGO_EMAIL, strEmail);
editorFicheroConf.putInt(PREFERENCIAS_JUEGO_GENERO, iGenero);
//TODO: Faltan los valores para la clave y la fecha de nacimiento

//Aplicamos los cambios al fichero de SharedPreferences:
editorFicheroConf.commit();
}

Como vemos primero creamos un objeto Editor (editorFicheroConf) asociado a nuestro archivo de SharedPreferences al utilizar la variable miembro mFicheroConfig.
Después obtenemos referencias a las vistas que queremos guardar y obtenemos sus valores. Por último guardamos los valores utilizando según proceda el método adecuado del editor (putString, putInt...). Por último aplicamos los cambios al fichero con el método commit(). En nuestro caso, y dado que no accedemos a este fichero en otro lado, podríamos utilizar el método apply(), que también aplica los cambios pero de forma asíncrona, primero a los valores en memoria y después inicia un proceso asíncrono para guardarlos en la carpeta correspondiente.

Ahora cada vez que pulsemos el botón “atrás”, al pasar nuestra actividad al estado de Pausa guardará los datos existentes en las vistas.

Quedan pendientes el guardado de los datos referentes a la fecha y a la clave, que los veremos próximamente.

Ver. 1.0 – Revisión 18/04/2012

No hay comentarios:

Publicar un comentario