Escolar Documentos
Profissional Documentos
Cultura Documentos
Android
Continuando con nuestros tutoriales de desarrollo android, en esta ocasin
veremos cmo usar bases de datos en SQLite para no perder la informacin de nuestras
aplicaciones Android.
A medida que vayamos avanzando veremos la utilidad de clases como
SQLiteOpenHelper, SQLiteDatabase, Cursor, CursorAdapter y de Herramientas
como sqlite3 y SQLite Browser.
Con el fin de facilitar tu aprendizaje usaremos un ejemplo de gua, que te permitir ir la
prctica en paralelo a las teoras y conceptos estudiados. Puedes descargar los recursos
desde aqu:
Qu es SQLite?
Es un ligero motor de bases de datos de cdigo abierto, que se caracteriza por
mantener el almacenamiento de informacin persistente de forma sencilla. A diferencia
de otros SGBD como MySQL, SQL Server y Oracle DB, SQLite tiene las siguientes
ventajas:
Es por eso que SQLite es una tecnologa cmoda para los dispositivos mviles. Su
simplicidad, rapidez y usabilididad permiten un desarrollo muy amigable.
SQLite tiene ciertas limitaciones en algunas operaciones. Por ejemplo, no se puede
implementar las clausulas FULL OUTER JOIN y RIGHT OUTER JOIN. Aunque en la
mayora de casos esto no afectar, siempre habrn otras alternativas como JavaDB o
MongoDB.
Para comenzar a probar nuestras bases de datos, quisiera explicarte un poco ms sobre
el ejemplo prctico que vamos a desarrollar. Se trata de una aplicacin llamada
Quotilius. Cuyo objetivo es guardar una lista de frases celebres.
body
author
El ignorante afirma, el sabio duda y
Aristteles
reflexiona
Hay derrotas que tienen ms
Jorge Luis
dignidad que la victoria
Borges
Si buscas resultados distintos, no
Albert Einstein
hagas siempre lo mismo
Donde mora la libertad, all est mi Benjamin
patria
Franklin
Ojo por ojo y todo el mundo acabar Mahatma
ciego
Gandhi
Luego recibes los datos con el mtodo onActivityResult() y realizas las operaciones
necesarias para guardar los datos en la base de datos:
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ADD_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
//Insertar registro en la base de datos
}
}
null,//factory
DATABASE_VERSION//int version
);
}
@Override
public void onCreate(SQLiteDatabase db) {
//Crear la base de datos
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int
newVersion) {
//Actualizar la base de datos
}
}
name: String
onCreate()
Este mtodo es llamado automticamente cuando creamos una instancia de la clase
SQLiteOpenHelper. En su interior establecemos la creacin de las tablas y registros.
Recibe como parmetro una referencia de la clase SQLiteDataBase, la cual representa
el esquema completo de la base de datos.
Por defecto el archivo de la base de datos ser almacenado en la direccin
/data/data/<paquete>/databases/<nombre-de-la-bd>.db de nuestro dispositivo
mvil.
onUpgrade()
Es ejecutado si se identific que el usuario tiene una versin antigua de la base de datos.
En su interior estableceremos instrucciones para modificar el esquema de la base de
datos, como por ejemplo eliminar todo el esquema y recrearlo, agregar una nueva tabla,
aadir una nueva columna, etc. Recibe tres parmetros:
de
datos.
newVersion: Entero
"\"Aristteles\")," +
"(null," +
"\"Hay derrotas que tienen mas dignidad que la
victoria\"," +
Como ves, es una clase muy completa que nos proporcionar flexibilidad al realizar
operaciones sobre la base de datos. Estas declaraciones facilitan la adaptacin del
esquema si en algn momento cambian los datos de las tablas o columnas.
Adicional a todas estas definiciones tenemos dos variables privadas: openHelper y
database. Ambas las usaremos en el constructor para acceder a la base de datos con el
mtodo getWritableDatabase(), el cual retorna en una instancia de SQLiteDatabase
que nos permitir leer y modificar la informacin de la base de datos directamente.
Lo primero que hicimos fue crear atributos de clase para el nombre de la base de datos y
la versin. Para crear la tabla Quotes llamamos al mtodo execSQL() de
SQLiteDataBase.
Este mtodo ejecuta una sola sentencia SQL que no retorne en filas. Por lo que el
comando SELECT no es posible usarlo dentro de l.
Evita ejecutar mltiples sentencias en una sola invocacin del mtodo execSQL().
Puede que se ejecute la primera, pero las otras no surtirn efecto.
Ahora solo queda por instancear un objeto QuotesDataSource en Main para que se cree
nuestra base de datos:
//Crear nuevo objeto QuotesDataSource
dataSource = new QuotesDataSource(this);
Al ejecutar la aplicacin se supone que la base de datos habr sido creada con xito en
el sistema de archivos de Android. Pero Cmo comprobar que as fue?la respuesta
la encontramos en el uso de las siguientes herramientas.
La Herramienta sqlite3
sqlite3 es una herramienta de administracin para nuestras bases de datos SQLite a
travs de la lnea de comandos. Normalmente puedes descargarla de la pgina oficial de
SQLite, pero tanto como la distribucin de Android y Android Studio ya la traen
consigo.
Si todo sali bien, veremos nuestro archivo Quotes.db. Procede a gurdalo con el botn
de la parte superior derecha denominado Pull a file from the device. En la siguiente
seccin veremos algo interesante con l.
Ya que hemos comprobado que existe nuestra base de datos, iniciaremos sqlite3 dentro
del dispositivo. Sigue los siguientes pasos:
Paso #1
Inicia el terminal de Windows (cmd) o usa la pestaa Terminal de Android Studio:
Paso #2
Paso #4
Inicia sqlite3 en el dispositivo con el siguiente comando:
root@android:/ # sqlite3 data/data/TUPAQUETE/databases/Quotes.db
La anterior instruccin accede a sqlite3 y al mismo tiempo le pide que abra la base de
datos expuesta en el directorio especificado. Si accedi a la base de datos vers los
siguientes mensajes:
SQLite version 3.7.11 2012-03-20 11:35:50
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite>
Paso #5
Usa el comando .schema de sqlite3 para ver el resumen del esquema de la base de datos
Quotes:
CREATE TABLE Quotes(_id integer primary key autoincrement,body text
not null,author text not null);
CREATE TABLE android_metadata (locale TEXT);
El Esquema muestra que nuestra tabla Quotes ha sido creada correctamente. La tabla
llamada android_metadata es parte de la metainformacin de la base de datos, por lo
que siempre la encontrars.
Otra forma de comprobar el esquema de nuestra base de datos es usar sqlite3.exe en
nuestro equipo local.
Ve a la ruta para encontrar la carpeta platform-tools del SDK de Android y ejecuta la
aplicacin.
Luego usa .open para abrir el archivo en una ruta especificada o copia y pega el archivo
Quotes.db en la carpeta:
sqlite>.open Quotes.db
SQLite Browser
Si deseas conocer una herramienta ms visual, entonces SQLite Browser es una opcin
que te gustara considerar. Se trata de un editor para archivos de bases de datos SQLite
de cdigo abierto y sper sencillo de usar.
Solo basta con iniciarlo en tu pc y arrastrar el archivo Quotes.db a su editor.
Inmediatamente nos mostrar el esquema en forma de tablas con interfaz grfica de
usuario, adems de permitirnos editar la estructura y ejecutar sentencias SQL dentro de
ella.
Lo primero que tenemos que hacer es crear un objeto del tipo ContentValues, el cual
permite almacenar una serie de datos(Valores) relacionados a una llave(Nombre de la
columna). Donde cada elemento es aadido con el mtodo put().
Luego invocamos a insert() a travs de la instancia de la base de datos. El primer
parmetro que recibe es el nombre de la tabla. El segundo parmetro establece que si el
objeto que contiene los valores est vaco, entonces no se debe insertar el registro en la
base de datos. Y el tercer parmetro es nuestro objeto ContentValues.
Con esta informacin ya puedes crear un mtodo de guardado en la clase
QuotesDataSource para aislar la complejidad de la actividad Main. A dicho mtodo le
llamars saveQuoteRow() y recibir el cuerpo de la frase y su autor:
public void saveQuoteRow(String body,String author){
//Nuestro contenedor de valores
ContentValues values = new ContentValues();
//Seteando body y author
values.put(QuotesDataSource.ColumnQuotes.BODY_QUOTES,body);
values.put(QuotesDataSource.ColumnQuotes.AUTHOR_QUOTES,author);
//Insertando en la base de datos
database.insert(QUOTES_TABLE_NAME,null,values);
}
Podras usar el comando execSQL() para ejecutar una sentencia INSERT, pero como
ests recibiendo datos externos, es mejor usar insert() para evitar inyecciones SQL.
Por ejemplo, si quisiramos consultar todos los datos de la tabla Quotes usaramos el
siguiente cdigo:
Cursor c = db.query(
"Quotes", //Nombre de la tabla
null, //Lista de Columnas a consultar
null, //Columnas para la clausula WHERE
null, //Valores a comparar con las columnas del WHERE
null, //Agrupar con GROUP BY
null, //Condicin HAVING para GROUP BY
null //Clausula ORDER BY
);
Este mtodo te ayuda a aadir todas las partes posibles de las cuales se podra componer
una consulta, adems que te protege de inyecciones SQL, separando las clausulas de los
argumentos. Ahora veamos el propsito de los parmetros:
selection: Es
selectionArgs[]: Es
la necesitas.
having: Establece
orderBy: Reordena
Tanto query() como rawQuery() retornan un objeto de tipo Cursor. Este objeto es un
apuntador al conjunto de valores obtenidos de la consulta. Al inicio el cursor apunta a
una direccin previa a la primera fila. La idea es leer cada fila moviendo el cursor a la
fila siguiente y as sucesivamente.
Emplea el mtodo booleano moveToNext() para recorrer el cursor. Su cometido es
apuntar al siguiente elemento del cursor, el cual retorna en true si fue posible o false si
ya no existen ms elementos.
Este concepto es similar a cuando vimos cursores en SQL Server o en MySQL. Donde
recorramos cada elemento con un bucle while hasta que ya no existieran ms elementos
que referenciar.
Veamos:
while(c.moveToNext()){
String body = c.getString(ColomunQuotes.BODY_QUOTES);
//Acciones con el valor obtenido
}
Como ves, usamos mtodos get para obtener el valor de cada columna a travs del
nombre o clave. Por ejemplo, al obtener el cuerpo de la frase usamos getString()
debido a que su tipo en la tabla es text. Si fueses a obtener el cdigo, entonces usas
getInt().
Puedes aprovechar este nuevo concepto e implementar un nuevo mtodo en la clase
QuotesDataSource llamado getAllQuotes(). Su objetivo es retornar en un cursor
todas las filas de la tabla Quotes, lo que asla la complejidad de la operacin sobre la
base de datos de la actividad Main:
public Cursor getAllQuotes(){
//Seleccionamos todas las filas de la tabla Quotes
return database.rawQuery(
"select * from " + QUOTES_TABLE_NAME, null);
}
La Clase CursorAdapter
Existe un adaptador especial para el manejo de bases de datos llamado CursorAdapter.
Esta clase permite poblar una lista a travs de un cursor. Es decir, el origen de datos no
ser una lista ni un arreglo, si no un cursor.
es una clase abstracta de la cual se ha de crear tu adaptador
personalizado. Con ArrayAdapter tenamos que sobrescribir el mtodo getView()
para inflar nuestras filas con los datos de la lista. Pero no es el caso con
CursorAdapter. Esta vez debemos sobrescribir dos mtodos aislados llamados
bindView() y newView().
CursorAdapter
Ahora solo debemos cargar nuestra actividad principal e instancear nuestro adaptador
con un cursor que apunte a todos los registros de nuestra tabla Quotes.
adapter = new QuotesAdapter(this, sourceData.getAllQuotes());
setAdapter(adapter);
La Clase SimpleCursorAdapter
Si el diseo de las filas de tu lista es sencillo, entonces la clase SimpleCursorAdapter
podra ahorrarte tiempo de desarrollo. Esta clase es una extensin de CursorAdapter
que posee una implementacin completa para los desarrolladores. Con ella no tenemos
que sobrescribir mtodos ni tampoco crear un archivo de diseo, ya que permite usar
layouts del sistema.
Nuestra aplicacin Quotilius tiene elementos sencillos, por qu slo usamos dos text
views para mostrar el cuerpo de la frase y el autor. Por esta razn podemos usar el
layout del sistema two_line_list_item. Fjate como sera la creacin de un nuevo
adaptador:
//Iniciando el nuevo Adaptador
adapter = new SimpleCursorAdapter(
this,//Context context
android.R.layout.two_line_list_item,//int layout
dataSource.getAllQuotes(),//Cursor c
new String[]
{ColumnQuotes.BODY_QUOTES,ColumnQuotes.AUTHOR_QUOTES},//String[] from
new int[]{android.R.id.text1, android.R.id.text2},//int[] to
SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER//int flags
);
setListAdapter(adapter);
actividad.
layout: Es el layour que usaremos para inflar los elementos de cada fila. En
nuestro caso usamos el prefabricado por Android para los elementos con dos text
views
c: Es
from: Es
to: Es