Использование CursorAdapters с Xamarin.Android
Android предоставляет классы адаптеров специально для отображения данных из запроса базы данных SQLite:
SimpleCursorAdapter — аналогично тому ArrayAdapter
, что его можно использовать без подклассов. Просто укажите необходимые параметры (например, сведения о курсоре и макете) в конструкторе, а затем назначьте им ListView
.
CursorAdapter — базовый класс, от который можно наследовать, когда требуется больше контроля над привязкой значений данных к элементам управления макетом (например, скрытие или отображение элементов управления или изменение их свойств).
Адаптеры курсоров предоставляют высокопроизводительный способ прокрутки длинных списков данных, хранящихся в SQLite. Используемый код должен определить SQL-запрос в объекте Cursor
, а затем описать создание и заполнение представлений для каждой строки.
Создание базы данных 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
будет создан в OnCreate
методе HomeScreen
действия. Базовый SQLiteOpenHelper
класс управляет настройкой файла базы данных и гарантирует, что SQL в своем OnCreate
методе выполняется только один раз. Этот класс используется в следующих двух примерах и SimpleCursorAdapter
CursorAdapter
.
Запрос курсора должен иметь целый столбец _id
для CursorAdapter
работы. Если в базовой таблице нет целочисленного столбца с именем _id
, используйте псевдоним столбца для другого уникального целого числа в RawQuery
том, что создает курсор. Дополнительные сведения см. в документации Android.
Создание курсора
В примерах используется преобразование RawQuery
SQL-запроса в Cursor
объект. Список столбцов, возвращаемый курсором, определяет столбцы данных, доступные для отображения в адаптере курсора. Код, создающий базу данных в методе SimpleCursorTableAdapter/HomeScreen.csOnCreate
, показан здесь:
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
для отображения строк в a ListView
.
Использование SimpleCursorAdapter
SimpleCursorAdapter
похож на ArrayAdapter
, но специализированный для использования с SQLite. Для него не требуется подкласс — просто задайте некоторые простые параметры при создании объекта, а затем назначьте его свойствуListView
Adapter
.
Параметры конструктора SimpleCursorAdapter:
Контекст — ссылка на содержащее действие.
Макет — идентификатор ресурса представления строк для использования.
ICursor — курсор, содержащий запрос SQLite для отображения данных.
Из массива строк — массив строк, соответствующих именам столбцов в курсоре.
Для целочисленного массива — массив идентификаторов макетов, соответствующих элементам управления в макете строки. Значение столбца, указанного в массиве 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
— это быстрый и простой способ отображения данных SQLite в объекте ListView
. Основное ограничение заключается в том, что он может привязать только значения столбцов для отображения элементов управления, он не позволяет изменять другие аспекты макета строки (например, отображение или скрытие элементов управления или изменение свойств).
Подклассы CursorAdapter
Подкласс CursorAdapter
имеет те же преимущества производительности, что SimpleCursorAdapter
и для отображения данных из SQLite, но также обеспечивает полный контроль над созданием и макетом каждого представления строк. Реализация CursorAdapter
отличается от подклассаBaseAdapter
, так как она не переопределяет GetView
или GetItemId
Count
this[]
индексатор.
Учитывая рабочую базу данных SQLite, необходимо переопределить два метода для создания подкласса CursorAdapter
:
BindView — с учетом представления обновите его, чтобы отобразить данные в предоставленном курсоре.
NewView — вызывается, когда
ListView
требуется новое представление для отображения. БудетCursorAdapter
заботиться о повторном использовании представлений (в отличиеGetView
от метода на обычных адаптерах).
Подклассы адаптера в предыдущих примерах имеют методы для возврата количества строк и извлечения текущего элемента— не требуются эти методы, CursorAdapter
так как эти сведения можно свести с самого курсора. Разделив создание и заполнение каждого представления на эти два метода, CursorAdapter
принудительное повторное использование представления. Это отличается от обычного адаптера, где можно игнорировать convertView
параметр BaseAdapter.GetView
метода.
Реализация CursorAdapter
Код в CursorTableAdapter/HomeScreenCursorAdapter.cs содержит CursorAdapter
подкласс. Он сохраняет ссылку на контекст, передаваемую в конструктор, чтобы получить доступ к LayoutInflater
методу NewView
. Полный класс выглядит следующим образом:
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
Activity
В открываемом ListView
элементе создайте курсор и CursorAdapter
назначьте его представлению списка.
Код, выполняющий это действие в методе CursorTableAdapter/HomeScreen.csOnCreate
, показан здесь:
// 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
ранее вызов метода.