Bases de datos

Las bases de datos son una herramienta de gran potencia en la creación de aplicaciones informáticas. Hasta hace muy poco resultaba costoso y complejo utilizar bases de datos en nuestras aplicaciones. No obstante, Android incorpora la librería SQLite, que nos permitirá utilizar bases de datos mediante el lenguaje SQL, de una forma sencilla y utilizando muy pocos recursos del sistema. Como verás en este apartado, almacenar tu información en una base de datos no es mucho más complejo que almacenarla en un fichero, y además resulta mucho más potente.

SQL es el lenguaje de programación más utilizado para bases de datos. No resulta complejo entender los ejemplos que se mostrarán en este libro. No obstante, si deseas hacer cosas más complicadas te recomiendo que consultes alguno de los muchos manuales que se han escrito sobre el tema.

Para manipular una base de datos en Android usaremos la clase abstracta SQLiteOpenHelper, que nos facilita tanto la creación automática de la base de datos como el trabajar con futuras versiones de esta base de datos. Para crear un descendiente de esta clase hay que implementar los métodos onCreate() y onUpgrade(), y opcionalmente, onOpen(). La gran ventaja de utilizar esta clase es que ella se preocupará de abrir la base de datos si existe, o de crearla si no existe. Incluso de actualizar la versión si decidimos crear una nueva estructura de la base de datos. Además, esta clase tiene dos métodos: getReadableDatabase() y getWritableDatabase(), que abren la base de datos en modo solo lectura o lectura y escritura. En caso de que todavía no exista la base de datos, estos métodos se encargarán de crearla.

video[Tutorial] Ciclo de vida de una aplicación en Android

Ejercicio: Utilizando una base de datos para guardar puntuaciones.

Pasemos a demostrar cómo guardar las puntuaciones obtenidas en Asteroides en una base de datos. Si comparas la solución propuesta con las anteriores verás como el código necesario es menor. Además, una base de datos te da mucha más potencia; puedes por ejemplo ordenar la salida por puntuación, eliminar filas antiguas, etc. Todo esto sin aumentar apenas el uso de recursos.

1.     Crea la clase AlmacenPuntuacionesSQLite en el proyecto Asteroides y escribe el siguiente código:

public class AlmacenPuntuacionesSQLite extends SQLiteOpenHelper
                                         implements AlmacenPuntuaciones{
   public AlmacenPuntuacionesSQLite(Context context) {
      super(context, "puntuaciones", null, 1);
   }

   //Métodos de SQLiteOpenHelper
   @Override public void onCreate(SQLiteDatabase db) {
      db.execSQL("CREATE TABLE puntuaciones ("+
            "_id INTEGER PRIMARY KEY AUTOINCREMENT, "+
            "puntos INTEGER, nombre TEXT, fecha BIGINT)");
   }

   @Override    public void onUpgrade(SQLiteDatabase db,
                                 int oldVersion, int newVersion) {
   // En caso de una nueva versión habría que actualizar las tablas
   }

   //Métodos de AlmacenPuntuaciones
   public void guardarPuntuacion(int puntos, String nombre,
                                                   long fecha) {
      SQLiteDatabase db = getWritableDatabase();
      db.execSQL("INSERT INTO puntuaciones VALUES ( null, "+
            puntos+", '"+nombre+"', "+fecha+")");
      db.close();
   }
   
   public Vector<String> listaPuntuaciones(int cantidad) {
      Vector<String> result = new Vector<String>();
      SQLiteDatabase db = getReadableDatabase();
      Cursor cursor = db.rawQuery("SELECT puntos, nombre FROM " +
       "puntuaciones ORDER BY puntos DESC LIMIT " +cantidad, null);
      while (cursor.moveToNext()){
            result.add(cursor.getInt(0)+" " +cursor.getString(1));
      }
      cursor.close();
      db.close();
      return result;
   }   
}

El constructor de la clase se limita a llamar al constructor heredado con el perfil:

SQLiteOpenHelper(Context contexto, String nombre, SQLiteDatabase.CursorFactory cursor, int version).

Los parámetros se describen a continuación:

contexto: Contexto usado para abrir o crear la base de datos.

nombre: Nombre de la base de datos que se creará. En nuestro caso “puntuaciones”.

cursor: Se utiliza para crear un objeto de tipo cursor. En nuestro caso no lo necesitamos.

version: Número de versión de la base de datos empezando desde 1. En el caso de que la base de datos actual tenga una versión más antigua se llamará a onUpgrade() para que actualice la base de datos.

 

El método onCreate() se invocará cuando sea necesario crear la base de datos. Como parámetro se nos pasa una instancia de la base de datos que se acaba de crear. Este es el momento de crear las tablas que contendrán información. En nuestra aplicación necesitamos solo la tabla puntuaciones que se crea por medio del comando SQL CREATE TABLE puntuaciones… El primer campo tiene por nombre _idy será un entero usado como clave principal. Su valor será introducido de forma automática por el sistema, de forma que dos registros no tengan nunca el mismo valor.

 

El método onUpgrade() está vacío. Si más adelante decidimos crear una nueva estructura para la base de datos, tendremos que indicar un número de versión superior, por ejemplo la 2. Cuando se ejecute el código sobre un sistema donde se disponga de una base de datos con la versión 1,  se incocará el método onUpgrade(). En él tendremos que escribir los comandos necesarios para transformar la antigua base de datos en la nueva, tratando de conservar la información de la versión anterior.

Pasemos a describir los dos métodos de la interfaz  AlmacenaPuntuaciones. El método guardarPuntuacion() comienza obteniendo una referencia a nuestra base de datos utilizando getWritableDatabase(),  mediante la cual ejecuta el comando SQL para almacenar un nueva fila en la tabla INSERT INTO puntuaciones … El método listaPuntuaciones() comienza obteniendo una referencia a nuestra base de datos utilizando getReadableDatabase(). Realiza una consulta utilizando el método rawQuery(), con la que obtiene un cursor que utiliza para leer todas las filas devueltas en la consulta.

2.     Modifica el código correspondiente para que este método pueda ser seleccionado para almacenar las puntuaciones.

3.     Verifica su funcionamiento.

Ejercicio: Verificación de los ficheros creados

1.     Abre la vista File Explorer. Pulsa el botón Android  Device Monitor () de la barra de herramientas y selecciona la lengüeta  File Explorer

2.     Busca la ruta data/data/org.example.asteroides

3.     Observa los ficheros creados y compara el tamaño de cada uno.