sábado, 14 de abril de 2012

Persistencia de datos con SQLite sobre Android: parte 2.


Desarrollo sobre la plataforma Android:


Hola a todos nuevamente, en este caso vamos a seguir un poco mas sobre el te de persistencia de datos, utilizando el motor de base de datos SQLite, pero a esto le sumaremos Data Binding y Content Provider ;). Que ahora pasaremos a explicar, porque y para que de los mismos.
Viendo el post anterior, ustedes se preguntaran para que queremos estas herramientas, ahora lo que deberíamos preguntarnos, (el porque de los Data Binding ), si tuviéramos el caso de que hubiera una cantidad de eventos enorme, todos ellos plasmados en una sola cadena, y nosotros querríamos tomar unos datos de la misma, pues se tornaría extremadamente lento, y además difícil de manejar.
Para no tener ese tipo de problemas vamos a utilizar los Data Binding, con los mismos podremos conectar nuestro modelo de datos con la vista donde querríamos reflejar los mismo, con unas pocas lineas de código, lo que hará que además de mas entendible el mismo, también mas efectivo ;)

Ahora para ir mostrando lo que estoy escribiendo, deberemos modificar un poco el código del anterior post, en este caso nuestra clase PruebaSQLiteActivity2 va a quedar de esta manera:

package com.prueba.gabriel.sqlite2;

import static android.provider.BaseColumns._ID;
import static com.prueba.gabriel.sqlite2.Constantes.TIME;
import static com.prueba.gabriel.sqlite2.Constantes.TITLE;
import static com.prueba.gabriel.sqlite2.Constantes.TABLE_NAME;
import com.prueba.gabriel.sqlite2.PruebaSQLiteDataHelper;
import com.prueba.gabriel.sqlite2.R;
import android.app.ListActivity;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.widget.SimpleCursorAdapter;

public class PruebaSQLiteActivity2 extends ListActivity {
private static String[] FROM = { _ID, TIME, TITLE, };
private static String ORDER_BY = TIME + " DESC";
private static int[] TO = { R.id.rowid, R.id.time, R.id.title, };
private PruebaSQLiteDataHelper pruebaSQLite;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
pruebaSQLite = new PruebaSQLiteDataHelper(this);
try {
addEvent("Pruebas con SQLite");
Cursor cursor = getEvents();
showEvents(cursor);
} finally {
pruebaSQLite.close();
}
}
private void addEvent(String string) {

SQLiteDatabase db = pruebaSQLite.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(TIME, System.currentTimeMillis());
values.put(TITLE, string);
db.insertOrThrow(TABLE_NAME, null, values);
}

private Cursor getEvents() {

SQLiteDatabase db = pruebaSQLite.getReadableDatabase();
Cursor cursor = db.query(TABLE_NAME, FROM, null, null, null,
null, ORDER_BY);
startManagingCursor(cursor);
return cursor;
}

private void showEvents(Cursor cursor) {

SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
R.layout.item, cursor, FROM, TO);
setListAdapter(adapter);
}

}

Data Binding:

El data binding nos va a permitir conectar nuestro modelo de datos con unas pocas lineas, no se si se acuerdan en el ejemplo anterior (si no, deberían volver a ver el anterior post ;) ) donde en el método showEvents, necesitas 10 lineas de código, cuando acá con solo 2 y de una manera sencilla ya lo logramos.

Vamos a pasar a explicar un poco las modificaciones del código, pues como principal modificación, pueden observar que la clase no extiende de Activity, ahora debemos extender de ListActivity (una clase que extiende de Activity). Luego como deje antes debemos modificar las lineas del método showEvents().
Como se puede ver es mucho mas fácil de comprender ese método ahora, pues en la primera linea solo creamos un SimpleCursorAdapter para el cursor, y en la segunda linea solo le decimos al ListActivity que utilice el nuevo adapter que nosotros creamos. El adapter simplemente actúa como un intermediario o una conexión entre la vista y el origen de datos que nosotros le configuremos.
El constructor de SimpleCursorAdapter toma 5 parámetros:

  • context : en este caso es this, porque es una referencia a la actividad actual.
  • Layout: este recursor define la lista de elementos de una lista única.
  • cursor: es el cursor del conjunto de datos.
  • From: Es la lista de nombres de columnas de donde vienen los datos.
  • To: La lista de vistas donde van a ir los datos.

Ahora como puede imaginar, debemos ver donde se desplegaran los datos, que en este caso sera en item.xml, y el codigo es el siguiente:

<?xml version="1.0" encoding="utf-8"?>
<!-- Prueba SQLite 2 ! -->
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:padding="10sp">
<TextView
android:id="@+id/rowid"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/rowidcolon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=": "
android:layout_toRightOf="@id/rowid" />
<TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/rowidcolon" />
<TextView
android:id="@+id/timecolon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=": "
android:layout_toRightOf="@id/time" />
<TextView
android:id="@+id/title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:textStyle="italic"
android:layout_toRightOf="@id/timecolon" />
</RelativeLayout>


Aunque esto paresca realmente complicado, pues no lo es para nada, solo es desplegar los datos con dos puntos entre los campos y toque un poquito el formato de salida, pero es muy simple.
Por ultimo, deberemos modificar un poco el layout principal, o sea el main.xml que antes teníamos, nos quedara así:

<?xml version="1.0" encoding="utf-8"?>
<!-- Prueba SQLite 2 !-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<!-- Note built-in ids for 'list' and 'empty' -->
<ListView
android:id="@android:id/list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@android:id/empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/empty" />
</LinearLayout>

A causa de que ListActivity extiende de Activity, en este caso Androi buscara dos ID especiales en el archivo layout, list y empty. Esto es para que si en el list view hay datos, pues esto se mostraran sin problemas(list), en cambio si no los hay, se mostrara la lista vacía (empty).
Por este motivo en nuestro archivo strings.xml agregamos el string: No hay evento!. Esto es para que si no hay datos, no se muestre una pantalla en blanco, si no el aviso de que no hay eventos ;).
Este es el archivo string.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

<string name="app_name">PruebaSQLite2</string>
<string name="empty">No hay evento!</string>

</resources>


Como se puede observar, en la siguiente imagen, este es el resultado de la aplicación:



Bueno gente, eso es todo por ahora, en el próximo post sobre SQLite vamos a ver lo que es un ContentProvider, para que sirve y como funciona ;) Espero que les allá gustado, como siempre les dejo los enlaces de la documentación de donde fue sacada esta información.

Documentación oficial:


Otros Enlaces:




Saludos a todos, Gabriel E. Pozo