Compartir a través de


Uso de CursorAdapters con Xamarin.Android

Android proporciona clases de adaptador específicamente para mostrar datos de una consulta de base de datos SQLite:

SimpleCursorAdapter: similar a un elemento ArrayAdapter porque se puede usar sin subclases. Simplemente proporcione los parámetros necesarios (como un cursor y la información de diseño) en el constructor y, a continuación, asígnelo a ListView.

CursorAdapter: una clase base de la que puede heredar cuando necesite más control sobre el enlace de valores de datos a controles de diseño (por ejemplo, ocultar o mostrar controles o cambiar sus propiedades).

Los adaptadores de cursor proporcionan una forma de alto rendimiento para desplazarse por listas largas de datos almacenados en SQLite. El código de consumo debe definir una consulta SQL en un objeto Cursor y, a continuación, describir cómo crear y rellenar las vistas para cada fila.

Creación de una base de datos SQLite

Para demostrar los adaptadores de cursor, se requiere una implementación sencilla de la base de datos SQLite. El código de SimpleCursorTableAdapter/VegetableDatabase.cs contiene el código y SQL para crear una tabla y rellenarla con algunos datos. La clase VegetableDatabase completa se muestra aquí:

class VegetableDatabase  : SQLiteOpenHelper {
   public static readonly string create_table_sql =
       "CREATE TABLE [vegetables] ([_id] INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE, [name] TEXT NOT NULL UNIQUE)";
   public static readonly string DatabaseName = "vegetables.db";
   public static readonly int DatabaseVersion = 1;
   public VegetableDatabase(Context context) : base(context, DatabaseName, null, DatabaseVersion) { }
   public override void OnCreate(SQLiteDatabase db)
   {
       db.ExecSQL(create_table_sql);
       // seed with data
       db.ExecSQL("INSERT INTO vegetables (name) VALUES ('Vegetables')");
       db.ExecSQL("INSERT INTO vegetables (name) VALUES ('Fruits')");
       db.ExecSQL("INSERT INTO vegetables (name) VALUES ('Flower Buds')");
       db.ExecSQL("INSERT INTO vegetables (name) VALUES ('Legumes')");
       db.ExecSQL("INSERT INTO vegetables (name) VALUES ('Bulbs')");
       db.ExecSQL("INSERT INTO vegetables (name) VALUES ('Tubers')");
   }
   public override void OnUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
   {   // not required until second version :)
       throw new NotImplementedException();
   }
}

Se creará una instancia de la clase VegetableDatabase en el método OnCreate de la actividad HomeScreen. La clase base SQLiteOpenHelper administra la configuración del archivo de base de datos y garantiza que el código SQL de su método OnCreate solo se ejecute una vez. Esta clase se usa en los dos ejemplos siguientes para SimpleCursorAdapter y CursorAdapter.

La consulta de cursor debe tener una columna de enteros _id para que CursorAdapter funcione. Si la tabla subyacente no tiene una columna de enteros denominada _id, use un alias de columna para otro entero único en RawQuery que compone el cursor. Consulte los documentos de Android para obtener más información.

Creación del cursor

Los ejemplos usan RawQuery para convertir una consulta SQL en un objeto Cursor. La lista de columnas que se devuelve del cursor define las columnas de datos que están disponibles para mostrarse en el adaptador de cursor. El código que crea la base de datos en el método SimpleCursorTableAdapter/HomeScreen.cs de OnCreate se muestra aquí:

vdb = new VegetableDatabase(this);
cursor = vdb.ReadableDatabase.RawQuery("SELECT * FROM vegetables", null); // cursor query
StartManagingCursor(cursor);
// use either SimpleCursorAdapter or CursorAdapter subclass here!

Cualquier código que llame a StartManagingCursor también debe llamar a StopManagingCursor. En los ejemplos se usa OnCreate para iniciar y OnDestroy para cerrar el cursor. El método OnDestroy contiene este código:

StopManagingCursor(cursor);
cursor.Close();

Una vez que una aplicación tiene disponible una base de datos SQLite y ha creado un objeto de cursor como se muestra, puede usar SimpleCursorAdapter o una subclase de CusorAdapter para mostrar filas en ListView.

Uso de SimpleCursorAdapter

SimpleCursorAdapter es como ArrayAdapter, pero especializado para usarlo con SQLite. No requiere subclases: solo tiene que establecer algunos parámetros simples al crear el objeto y, a continuación, asignarlo a una propiedad Adapter de ListView.

Los parámetros del constructor SimpleCursorAdapter son:

Contexto: referencia a la actividad contenedora.

Diseño: el id. de recurso de la vista de fila que se va a usar.

ICursor: un cursor que contiene la consulta SQLite para que se muestren los datos.

Desde la matriz de cadenas: matriz de cadenas correspondiente a los nombres de las columnas del cursor.

Para la matriz de enteros: matriz de id. de diseño que corresponden a los controles del diseño de fila. El valor de la columna especificada en la matriz from se enlazará al ControlID especificado en esta matriz en el mismo índice.

Las matrices from y to deben tener el mismo número de entradas porque forman una asignación del origen de datos a los controles de diseño de la vista.

El código de ejemplo SimpleCursorTableAdapter/HomeScreen.cs conecta un elemento SimpleCursorAdapter así:

// which columns map to which layout controls
string[] fromColumns = new string[] {"name"};
int[] toControlIDs = new int[] {Android.Resource.Id.Text1};
// use a SimpleCursorAdapter
listView.Adapter = new SimpleCursorAdapter (this, Android.Resource.Layout.SimpleListItem1, cursor,
       fromColumns,
       toControlIDs);

SimpleCursorAdapter es una manera rápida y sencilla de mostrar datos de SQLite en ListView. La limitación principal es que solo puede enlazar valores de columna para mostrar controles, no permite cambiar otros aspectos del diseño de fila (por ejemplo, mostrar u ocultar controles o cambiar propiedades).

Creación de subclases de CursorAdapter

Una subclase CursorAdapter tiene las mismas ventajas de rendimiento que SimpleCursorAdapter para mostrar datos de SQLite, pero también le proporciona un control completo sobre la creación y el diseño de cada vista de fila. La implementación CursorAdapter es muy diferente de la creación de subclases BaseAdapter porque no invalida GetView, GetItemId, Count o el indexador this[].

Dada una base de datos SQLite en funcionamiento, solo tiene que invalidar dos métodos para crear una subclase CursorAdapter:

  • BindView: dada una vista, actualícela para mostrar los datos en el cursor proporcionado.

  • NewView: se llama cuando ListView requiere que se muestre una nueva vista. CursorAdapter se encargará de reciclar vistas (a diferencia del método GetView en adaptadores normales).

Las subclases del adaptador en ejemplos anteriores tienen métodos para devolver el número de filas y para recuperar el elemento actual: CursorAdapter no requiere estos métodos porque esa información se puede obtener del propio cursor. Al dividir la creación y el rellenado de cada vista en estos dos métodos, CursorAdapter exige reutilizar la vista. Esto contrasta con un adaptador normal en el que es posible omitir el parámetro convertView del método BaseAdapter.GetView.

Implementación de CursorAdapter

El código de CursorTableAdapter/HomeScreenCursorAdapter.cs contiene una subclase CursorAdapter. Almacena una referencia de contexto que se pasa al constructor para que pueda acceder a LayoutInflater en el método NewView. La clase completa tiene este aspecto:

public class HomeScreenCursorAdapter : CursorAdapter {
   Activity context;
   public HomeScreenCursorAdapter(Activity context, ICursor c)
       : base(context, c)
   {
       this.context = context;
   }
   public override void BindView(View view, Context context, ICursor cursor)
   {
       var textView = view.FindViewById<TextView>(Android.Resource.Id.Text1);
       textView.Text = cursor.GetString(1); // 'name' is column 1 in the cursor query
   }
   public override View NewView(Context context, ICursor cursor, ViewGroup parent)
   {
       return this.context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleListItem1, parent, false);
   }
}

Asignación de CursorAdapter

En la Activity que mostrará ListView, cree el cursor y CursorAdapter lo asignará después a la vista de lista.

El código que realiza esta acción en el método CursorTableAdapter/HomeScreen.cs de OnCreate se muestra aquí:

// create the cursor
vdb = new VegetableDatabase(this);
cursor = vdb.ReadableDatabase.RawQuery("SELECT * FROM vegetables", null);
StartManagingCursor(cursor);

// create the CursorAdapter
listView.Adapter = (IListAdapter)new HomeScreenCursorAdapter(this, cursor, false);

El método OnDestroy contiene la llamada de método StopManagingCursor descrita anteriormente.