Skip to content
Andrés Matte edited this page Feb 25, 2016 · 4 revisions

En android se pueden guardar información de diferentes maneras, pero en este caso utilizaremos bases de datos. Usaremos SQLite, el sistema por defecto para android. En esta parte del tutorial no se ahondará de sobremanera debido a que es un tema transversal y hay mucha documentación al respecto.

Qué haremos

  1. Definir un esquema y sus constantes

  2. Crear base de datos y tablas

  3. Crear métodos CRUD

Definir un esquema y sus constantes

Una vez que el modelo relacional esté definido este se debe plasmar en una clase que llamaremos DatabaseContract. Esta tendrá definidas como String los nombres de las tablas, de las columnas y algunas operaciones importantes. Gracias a esto podemos cambiar el nombre de, por ejemplo, una columna sin la necesidad de cambiar el resto de nuestro código.

    // DatabaseContract.java
    public final class DatabaseContract {

        public DatabaseContract() {
        }

        public static abstract class Students implements BaseColumns {
            // BaseColumns nos entrega las constantes \_ID y \_COUNT

            public static final String TABLE_NAME = "STUDENTS";
            public static final String COLUMN_NAME_STUDENT_NAMES = "names";
            public static final String COLUMN_NAME_FIRST_LASTNAME = "firstlastname";
            public static final String COLUMN_NAME_SECOND_LASTNAME = "secondlastname";
            public static final String COLUMN_ID_CLOUD = "idcloud";

            public static final String TEXT_TYPE = " TEXT";
            public static final String INTEGER_TYPE = " INTEGER";
            public static final String COMMA_SEP = ",";

            public static final String SQL_CREATE_STUDENTS_TABLE =
                    "CREATE TABLE " + Students.TABLE_NAME + " (" +
                            Students.\_ID + " INTEGER PRIMARY KEY," +
                            Students.COLUMN_NAME_STUDENT_NAMES + TEXT_TYPE + COMMA_SEP +
                            Students.COLUMN_NAME_FIRST_LASTNAME + TEXT_TYPE + COMMA_SEP +
                            Students.COLUMN_NAME_SECOND_LASTNAME + TEXT_TYPE + COMMA_SEP+
                            Students.COLUMN_ID_CLOUD + INTEGER_TYPE +
                            " )";

            public static final String SQL_DELETE_STUDENTS =
                    "DROP TABLE IF EXISTS " + Students.TABLE_NAME;
        }
    }

Crear base de datos y tablas

Ahora utlizaremos la clase SQLiteOpenHelper, una API para poder interactuar con nuestra base de datos de manera lazy. Esto quiere decir que la base de datos, o la conexión con ella, es creada solo en caso de ser necesitada. Esto ocurrirá cuando se llame a getWritableDatabase() o a getReadableDatabase().

Las instancias de SQLiteDatabase retornadas por estos métodos están especialmente configuradas para realizar las operaciones especificadas. Esto quiere decir que getWritableDatabase() retornará una instancia en el que la escritura de datos será rápida en desmedro de la lectura. En cambio, con getReadableDatabase() se tendrá una lectura más rápida. Además, al llamar a estos métodos se crea la base de datos en caso de no existir aún.

Otro método esencial es onCreate(SQLiteDatabase). Ahí es donde se ejecuta el código SQL para crear las tablas de la base de datos.

    // StudentsDbHelper.java
    // Documentacion:
    // http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html
    import android.content.Context;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteOpenHelper;

    public class StudentsDbHelper extends SQLiteOpenHelper {

        public static final int DATABASE_VERSION = 1;
        public static final String DATABASE_NAME = "Students.db";

        private static StudentsDbHelper sInstance;

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

        // Nos aseguramos de que solo haya una instancia para evitar errores.
        // Mas detalles:
        // http://www.androiddesignpatterns.com/2012/05/correctly-managing-your-sqlite-database.html
        public static synchronized StudentsDbHelper getInstance(Context context) {
            if (sInstance == null) {
                sInstance = new StudentsDbHelper(context.getApplicationContext());
            }
            return sInstance;
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(DatabaseContract.Students.SQL_CREATE_STUDENTS_TABLE);
        }

        // Cambia la version del esquema en caso de haber modificaciones.
        // Por simplicidad asumimos que esto no va a pasar y tan solo se resetea la db.
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            db.execSQL(DatabaseContract.Students.SQL_DELETE_STUDENTS);
            onCreate(db);
        }
    }

Para escribir en la base de datos se debe obtener una instacia de StudentsDbHelper para luego obtener una de la base de datos adaptada para escritura.

    StudentsDbHelper mDbHelper = StudentsDbHelper.newInstance();
    SQLiteDatabase db = mDbHelper.getWritableDatabase();

Para leer se debe obtener una instancia adaptada para la lectura.

    StudentsDbHelper mDbHelper = StudentsDbHelper.newInstance();
    SQLiteDatabase db = mDbHelper.getReadableDatabase();

Crear métodos CRUD

Agregar datos

Para insertar datos se deben ingresar los datos del elemento a añadir en ContentValues y usar el método insert. El segundo argumento especifica la columna en que la base de datos puede puede insertar null si values (los datos a ingresar) está vacio. Si es que no quieres que se ingrese un record con valores vacios debes setearlo como null. Por ejemplo, si se quiere añadir un estudiante:

    // Codigo para insertar nuevo estudiante

    if (mDbHelper == null) {
        mDbHelper = StudentsDbHelper.getInstance(getActivity());
    }
    SQLiteDatabase db = mDbHelper.getWritableDatabase();

    ContentValues values = new ContentValues();
    values.put(DatabaseContract.Students.COLUMN_NAME_STUDENT_NAMES, student.getNames());
    values.put(DatabaseContract.Students.COLUMN_NAME_FIRST_LASTNAME, student.getFirstLastname());
    values.put(DatabaseContract.Students.COLUMN_NAME_SECOND_LASTNAME, student.getSecondLastname());
    values.put(DatabaseContract.Students.COLUMN_ID_CLOUD, student.getIdCloud());

    // Retorna la columna en la que fue insertado
    long success = db.insert(
            DatabaseContract.Students.TABLE_NAME,
            null,
            values);

    if (success >= 0) return true;
    return false;

Consultar datos

Para consultar datos se usa el método query(). Si no se quiere filtrar y solo obtener toda la información de la tabla se pueden dejar todos los valores como null excepto el nombre de la tabla. Por ejemplo para seleccionar todos los estudiantes:

    // Codigo para seleccionar todos los estudiantes

    if (mDbHelper == null) {
        mDbHelper = StudentsDbHelper.getInstance(getActivity());
    }

    // Selecciono las columnas que debe retornar de cada fila. Podria dejarse como null y me retorna todas.
    String[] projection = {DatabaseContract.Students.COLUMN_NAME_STUDENT_NAMES,
                           DatabaseContract.Students.COLUMN_NAME_FIRST_LASTNAME,
                           DatabaseContract.Students.COLUMN_NAME_SECOND_LASTNAME,
                           DatabaseContract.Students.COLUMN_ID_CLOUD
                           };

    // Se deja como null porque no se requiere filtrar. Por ejemplo, si se necesitara filtrar por primer apellido:
    // String selection = DatabaseContract.Students.COLUMN_NAME_FIRST_LASTNAME + "= ?"
    String selection = null;

    // Que el primer apellido sea Perez:
    // String[] selectionArgs = new String[]{ "Perez" };
    // En este caso dejamos como null
    String[] selectionArgs = null;

    SQLiteDatabase db = mDbHelper.getReadableDatabase();

    Cursor c = db.query(DatabaseContract.Students.TABLE_NAME,   // Tabla
                        projection,                             // Columnas a retornar
                        selection,                              // Columnas de WHERE
                        selectionArgs,                          // Valores de WHERE
                        null,                                   // Group by
                        null,                                   // Filtro por columnas de grupos
                        DatabaseContract.Students.COLUMN_NAME_FIRST_LASTNAME +" ASC"); // Ordenados

    ArrayList<Student> studentsInDb = new ArrayList<Student>();

    c.moveToFirst();

    if (c.getCount()<1){
        return false;
    }

    while (c.moveToNext()){
        String names = c.getString(c.getColumnIndexOrThrow(DatabaseContract.Students.COLUMN_NAME_STUDENT_NAMES))
                    .toUpperCase();
        String firstLast = c.getString(c.getColumnIndexOrThrow(DatabaseContract.Students.COLUMN_NAME_FIRST_LASTNAME))
                    .toUpperCase();
        String secondLast = c.getString(c.getColumnIndexOrThrow(DatabaseContract.Students.COLUMN_NAME_SECOND_LASTNAME))
                    .toUpperCase();
        int idCloud = c.getInt(c.getColumnIndexOrThrow(DatabaseContract.Students.COLUMN_ID_CLOUD));

        studentsInDb.add(new Student(names, firstLast, secondLast, idCloud));
    }

Borrar datos

Se utiliza el método delete.

Actualizar datos

Se utiliza el método update.


Siguiente: Content Provider.