将 CursorAdapters 与 Xamarin.Android 配合使用
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
方法调用。