Android 专门提供了适配器类来显示 SQLite 数据库查询中的数据:
SimpleCursorAdapter – 类似于 ArrayAdapter,因为它可以在不子类化的情况下使用。 只需在构造函数中提供所需的参数(如游标和布局信息),然后分配给一个 ListView。
CursorAdapter – 一个基类,当需要对将数据值绑定到布局控件进行更多控制时(例如隐藏/显示控件或更改其属性),可以继承该基类。
游标适配器提供了一种高性能方法,用于滚动浏览存储在 SQLite 中的数据的长列表。 使用的代码必须在 Cursor 对象中定义 SQL 查询,然后描述如何为每个行创建和填充视图。
创建 SQLite 数据库
若要演示游标适配器,需要一个简单的 SQLite 数据库实现。 SimpleCursorTableAdapter/VegetableDatabase.cs 中的代码包含用于创建表并使用某些数据填充表的代码和 SQL。
完整的 VegetableDatabase 类如下所示:
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();
}
}
VegetableDatabase 类将在 HomeScreen 活动的 OnCreate 方法中实例化。 SQLiteOpenHelper 基类管理数据库文件的设置,并确保其 OnCreate 方法中的 SQL 仅运行一次。 此类在以下两个示例中用于 SimpleCursorAdapter 和 CursorAdapter。
游标查询必须具有一个整数列 _id 才能使 CursorAdapter 正常工作。 如果基础表没有名为 _id 的整数列,则对构成游标的 RawQuery 中另一个唯一整数使用列别名。 有关详细信息,请参阅 Android 文档。
创建游标
这些示例使用 RawQuery 将 SQL 查询转换为 Cursor 对象。 从游标返回的列列表定义可用于在游标适配器中显示的数据列。 此处显示了在 SimpleCursorTableAdapter/HomeScreen.cs OnCreate 方法中创建数据库的代码:
vdb = new VegetableDatabase(this);
cursor = vdb.ReadableDatabase.RawQuery("SELECT * FROM vegetables", null); // cursor query
StartManagingCursor(cursor);
// use either SimpleCursorAdapter or CursorAdapter subclass here!
调用 StartManagingCursor 的任何代码也应调用 StopManagingCursor。 这些示例使用 OnCreate 启动游标,使用 OnDestroy 关闭游标。 OnDestroy 方法包含以下代码:
StopManagingCursor(cursor);
cursor.Close();
一旦应用程序具有可用的 SQLite 数据库并已创建所示的游标对象,它就可以利用 SimpleCursorAdapter 或 CusorAdapter 的子类来显示 ListView 中的行。
使用 SimpleCursorAdapter
SimpleCursorAdapter 就像 ArrayAdapter,但它专用于 SQLite。 它不需要子类化 – 只需在创建对象时设置一些简单参数,然后将其分配给 ListView 的 Adapter 属性。
SimpleCursorAdapter 构造函数的参数包括:
Context – 对包含活动的引用。
Layout – 要使用的行视图的资源 ID。
ICursor – 包含使数据显示的 SQLite 查询的游标。
From 字符串数组 – 对应于游标中列名称的字符串数组。
To 整数数组 – 与行布局中的控件对应的布局 ID 的数组。 from 数组中指定的列的值将绑定到此数组中指定的同一索引处的 ControlID。
from 和 to 数组必须具有相同数量的条目,因为它们构成了从数据源到视图中布局控件的映射。
SimpleCursorTableAdapter/HomeScreen.cs 示例代码连接 SimpleCursorAdapter 的方式如下:
// 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 是一种在 ListView 中显示 SQLite 数据的快速简单方法。 主要局限是它只能绑定列值以显示控件,它不允许更改行布局的其他方面(例如,显示/隐藏控件或更改属性)。
子类化 CursorAdapter
在显示 SQLite 中的数据方面,CursorAdapter 子类的性能优势与 SimpleCursorAdapter 相同,但它还让你能够完全控制每个行视图的创建和布局。 CursorAdapter 实现与子类化 BaseAdapter 大不相同,因为它不会替代 GetView、GetItemId、Count 或 this[] 索引器。
给定一个工作 SQLite 数据库,只需替代两个方法来创建 CursorAdapter 子类:
BindView – 给定一个视图,更新它以显示所提供的游标中的数据。
NewView – 当
ListView需要显示新视图时调用。CursorAdapter将处理视图回收(与常规适配器上的GetView方法不同)。
前面的示例中的适配器子类具有返回行数和检索当前项的方法 – CursorAdapter 不需要这些方法,因为可以从游标本身收集该信息。 通过将每个视图的创建和填充拆分为这两个方法,CursorAdapter 强制重用视图。 这与常规适配器形成鲜明对比,常规适配器可以忽略 BaseAdapter.GetView 方法的 convertView 参数。
实现 CursorAdapter
CursorTableAdapter/HomeScreenCursorAdapter.cs 中的代码包含 CursorAdapter 子类。 它存储传入构造函数的上下文引用,以便它可以访问 NewView 方法中的 LayoutInflater。 完整的类如下所示:
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);
}
}
分配 CursorAdapter
在将显示 ListView 的 Activity 中,创建游标,然后 CursorAdapter 将其分配给列表视图。
此处显示了在 CursorTableAdapter/HomeScreen.cs OnCreate 方法中执行此操作的代码:
// 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);
OnDestroy 方法包含前面所述的 StopManagingCursor 方法调用。