Использование 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 методе выполняется только один раз. Этот класс используется в следующих двух примерах и SimpleCursorAdapterCursorAdapter.

Запрос курсора должен иметь целый столбец _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. Для него не требуется подкласс — просто задайте некоторые простые параметры при создании объекта, а затем назначьте его свойствуListViewAdapter.

Параметры конструктора 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или GetItemIdCountthis[] индексатор.

Учитывая рабочую базу данных 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 ранее вызов метода.