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 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étodoGetView
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 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.