Адаптеры и списки
ListView и ArrayAdapter
Android представляет широкую палитру элементов,которые представляют списки. Все они является наследниками класса android.widget.AdapterView . Это такие виджеты как ListView, GridView, Spinner. Они могут выступать контейнерами для других элементов управления
При работе со списками мы имеем дело с тремя компонентами. Во-первых, это визуальный элемент или виджет, который на экране представляет список (ListView, GridView) и который отображает данные. Во-вторых, это источник данных — массив, объект ArrayList, база данных и т.д., в котором находятся сами отображаемые данные. И в-третьих, это адаптер — специальный компонент, который связывает источник данных с виджетом списка.
Одним из самых простых и распространенных элементов списка является виджет ListView . Рассмотрим связь элемента ListView с источником данных с помощью одного из таких адаптеров — класса ArrayAdapter .
Класс ArrayAdapter представляет собой простейший адаптер, который связывает массив данных с набором элементов TextView , из которых, к примеру, может состоять ListView . То есть в данном случае источником данных выступает массив объектов. ArrayAdapter вызывает у каждого объекта метод toString() для приведения к строковому виду и полученную строку устанавливает в элемент TextView.
Посмотрим на примере. Итак, разметка приложения может выглядеть так:
Здесь также определен элемент ListView, который будет выводить список объектов. Теперь перейдем к коду activity и свяжем ListView через ArrayAdapter с некоторыми данными:
Здесь вначале получаем по id элемент ListView и затем создаем для него адаптер.
Для создания адаптера использовался следующий конструктор ArrayAdapter (this,android.R.layout.simple_list_item_1, countries) , где
this : текущий объект activity
android.R.layout.simple_list_item_1 : файл разметки списка, который фреймворк представляет по умолчанию. Он находится в папке Android SDK по пути platforms/[android-номер_версии]/data/res/layout. Если нас не удовлетворяет стандартная разметка списка, мы можем создать свою и потом в коде изменить id на id нужной нам разметки
countries : массив данных. Здесь необязательно указывать именно массив, это может быть список ArrayList .
В конце неоходимо установить для ListView адаптер с помощью метода setAdapter() .
Источник
Адаптеры
В Android часто используются адаптеры. Если говорить в общих чертах, то адаптеры упрощают связывание данных с элементом управления. Адаптеры используются при работе с виджетами, которые дополняют android.widget.AdapterView: ListView, ExpandableListView, GridView, Spinner, Gallery, а также в активности ListActivity и др. Сам AdapterView дополняет android.widget.ViewGroup.
Итак, у нас есть набор объектов и есть компонент View. Назначение адаптера заключается в том, чтобы предоставлять дочерние виды для контейнера. Адаптер берет данные и метаданные определенного контейнера и строит каждый дочерний вид. Например, мы формируем пункты списка (массив строк) и передаём его списку ListView.
Вы что-нибудь поняли? Мой кот тоже ничего не понял. Попробуем объяснить по-другому. Что такое вообще адаптер? Это переходник между двумя какими-то предметами. Допустим, между питьевой водой и котом требуется адаптер в виде крана.
В данном случае адаптер спроектирован плохо, приходится изворачиваться.
Однако вернёмся к Android. В приложениях очень часто используется список на основе ListView. Сам список состоит из множества элементов TextView, которые идут друг за другом. Но их количество будет зависеть от того, чтобы мы хотим отобразить. Если нам нужны дни недели, то достаточно семи элементов, если месяцы, то уже двенадцать, ну а если нам нужны имена котов в Кот д’Ивуаре, то счёт пойдет на сотни. Короче говоря, нам нужно составить данные, например, в виде массива и скормить его списку. Адаптер этим и занимается. Он берёт по порядку предоставленные данные и размещает их в списке по порядку. При этом адаптер на лету создаёт нужные компоненты TextView и помещает в него приготовленный текст. Данные могут быть находиться не только в массиве, но и в базе данных. Для такого случая используется другой адаптер. А также вы можете придумать свой адаптер. Существуют уже готовые адаптеры на самые распространённые случаи и их предназначение можно определить по именам. Например, ArrayAdapter использует массив, а CursorAdapter работает с объектом Cursor, используемый в базах данных.
Готовые адаптеры
Все адаптеры, содержащиеся в Android, дополняют базовый адаптер BaseAdapter. Вот список готовых адаптеров:
- ArrayAdapter — предназначен для работы с ListView. Данные представлены в виде массива, которые размещаются в отдельных элементах TextView
- ListAdapter — адаптер между ListView и данными. Строго говоря, это класс-интерфейс, который можно использовать и в ArrayAdapter и в SimpleAdapter и т.д.
- SpinnerAdapter — адаптер для связки данных с элементом Spinner. Это тоже интерфейс, как ListAdapter и работает по схожему принципу
- SimpleAdapter — адаптер, позволяющий заполнить данными список более сложной структуры, например, два текста в одной строке списка.
- SimpleCursorAdapter — дополняет ResourceCursorAdapter и создаёт компоненты TextView/ImageView из столбцов, содержащихся в курсоре. Компоненты определяются в ресурсах
- CursorAdapter — предназначен для работы с ListView, предоставляет данные для списка через курсор, который должен иметь колонку с именем «_id»
- ResourceCursorAdapter — этот адаптер дополняет CursorAdapter и может создавать виды из ресурсов
- HeaderViewListAdapter — расширенный вариант ListAdapter, когда ListView имеет заголовки.
- WrapperListAdapter — еще один адаптер для списков.
BaseAdapter
Стандартные адаптеры не всегда покрывают потребности программиста. Если вам нужен свой собственный адаптер, то в Android есть абстрактный класс BaseAdapter, который можно расширить. Собственный адаптер необходим в тех случаях, когда требуется специальное управление данными или дополнительный контроль над отображением дочерних представлений. Кроме того, вы можете предусмотреть в своём адаптере элементы кэширования для повышения производительности работы.
Пример использования адаптере на основе BaseAdapter можно увидеть при создании GridView с картинками и в других примерах.
У BaseAdapter есть несколько методов, которые следует переопределить. Например, метод getCount() позволяет узнать количество выводимых объектов.
Другой важный метод адаптера — getView(), который отвечает за создание отдельных элементов списка. Он вызывается для каждого элемента списка, чтобы определить, какие данные нужно отобразить. Метод getVew() содержит параметр convertView, который позволяет использовать заново уже существующий элемент списка, который не отображается, т.к. пользователь пролистнул его с видимой части дисплея. Если convertView не пустой, он может быть использован заново, чтобы не грузить разметку списка. Подобный подход способствует увеличению производительности.
Метод getView() возвращает View, который фактически является контейнером ViewGroup и содержит в себе другие компоненты, например, ImageView или TextView.
На сайте представлены (будут представлены) практически все примеры с адаптерами. Оставайтесь на связи!
Источник
Полный список
— разбираемся в адаптерах
На последних уроках мы использовали адаптеры и сейчас вполне можем сформулировать, что это такое. Адаптер – мост между набором данных и объектом, использующим эти данные. Также адаптер отвечает за создание View-компонента для каждой единицы данных из набора.
Я по себе помню, что новичку непросто разобраться в адаптерах. Кажется, что их куча и абсолютно непонятно какой и где используется. И рассказывать об этом без практики – бессмысленно. Поэтому в своих уроках я сначала рассмотрел пару примеров, чтобы в голове сложилась схема использования: набор данных – адаптер – объект. И теперь проще будет разобрать, какие еще адаптеры есть и чем они отличаются.
В рассмотренных нами примерах были:
— адаптер ArrayAdapter и объект для отображения данных ListView
— адаптер SimpleExpandableListAdapter и объект ExpandableListView.
Я попробую в этом материале сделать обзор адаптеров и показать, чем они отличаются друг от друга. Материал будет периодически обновляться и пополняться. А пока я накидал схему java-иерархии интерфейсов и классов адаптеров. В скобках указываю тип: I – это интерфейс, AC – абстрактный класс, C – класс. Линии – это наследование. Читать следует сверху вниз.
Давайте по порядку смотреть, зачем оно все нужно.
Интерфейс Adapter. Описывает базовые методы, которые должны содержать адаптеры: getCount, getItem, getView и пр.
Интерфейс ListAdapter. Этот интерфейс должен быть реализован адаптером, который будет использован в ListView (метод setAdapter). Содержит описание методов для работы с разделителями(separator) списка.
Интерфейс SpinnerAdapter. Адаптеры, реализующие этот интерфейс, используются для построения Spinner(выпадающий список или drop-down). Содержит метод getDropDownView, который возвращает элемент выпадающего списка. На офиц.сайте есть пример использования.
Интерфейс WrapperListAdapter. Адаптеры, наследующие этот интерфейс используются для работы с вложенными адаптерами. Содержит метод getWrappedAdapter, который позволяет вытащить из основного адаптера вложенный. Чуть дальше поясню.
Класс HeaderViewListAdapter. Готовый адаптер для работы с Header и Footer. Внутри себя содержит еще один адаптер (ListAdapter), который можно достать с помощью выше рассмотренного метода getWrappedAdapter из интерфейса WrapperListAdapter.
Абстрактный класс BaseAdapter. Содержит немного своих методов и реализует методы интерфейсов, которые наследует, но не все. Своим наследникам оставляет на обязательную реализацию методы: getView, getItemId, getItem, getCount из ListAdapter. Т.е. если хотите создать свой адаптер – это класс вам подходит.
Класс ArrayAdapter . Готовый адаптер, который мы уже использовали. Принимает на вход список или массив объектов, перебирает его и вставляет строковое значение в указанный TextView. Кроме наследуемых методов содержит методы по работе с коллекцией данных – add, insert, remove, sort, clear и метод setDropDownViewResource для задания layout-ресурса для отображения пунктов выпадающего списка.
Класс SimpleAdapter. Также готовый к использованию адаптер. Принимает на вход список Map-объектов, где каждый Map-объект – это список атрибутов. Кроме этого на вход принимает два массива – from[] и to[]. В to указываем id экранных элементов, а в from имена(key) из объектов Map, значения которых будут вставлены в соответствующие (из from) экранные элементы.
Т.е. SimpleAdapter – это расширенный ArrayAdapter. Если вы делаете ListView и у вас каждый пункт списка содержит не один TextView, а несколько, то вы используете SimpleAdapter. Кроме наследуемых методов SimpleAdapter содержит методы по наполнению View-элементов значениями из Map – setViewImage, setViewText, setViewBinder. Т.е. видим, что он умеет работать не только с текстом, но и с изображениями. Метод setViewBinder – отличная штука, позволяет вам написать свой парсер значений из Map в View-элементы и адаптер будет использовать его. Это мы еще детально обсудим в дальнейших уроках.
Также содержит реализацию метода setDropDownViewResource.
Абстрактный класс CursorAdapter. Реализует абстрактные методы класса BaseAdapter, содержит свои методы по работе с курсором и оставляет наследникам методы по созданию и наполнению View: newView, bindView.
Абстрактный класс ResourceCursorAdapter. Содержит методы по настройке используемых адаптером layout-ресурсов. Реализует метод newView из CursorAdapter.
Класс SimpleCursorAdapter. Готовый адаптер, похож, на SimpleAdapter. Только использует не набор объектов Map, а Cursor, т.е. набор строк с полями. Соответственно в массив from[] вы заносите наименования полей, значения которых хотите вытащить в соответствующие View из массива to.
Содержит метод convertToString, который возвращает строковое значение столбца, который задается методом setStringConversionColumn. Либо можно задать свой конвертер методом setCursorToStringConverter и адаптер будет использовать его при вызове convertToString. В этом конвертере вы уже сами реализуете, что он будет возвращать.
Итого мы получили 4 готовых адаптера: HeaderViewListAdapter, ArrayAdapter , SimpleAdapter, SimpleCursorAdapter. Какой из них использовать — решать вам. Если у вас есть массив строк — то, не раздумывая, берете ArrayAdapter. Если работаете с БД и есть курсор, данные из которого надо вывести в список — используете SimpleCursorAdapter.
Если же эти адаптеры вам не подходят, есть набор абстрактных классов и интерфейсов, которые можем наследовать и реализовать в своих классах для создания своего адаптера. Да и готовые адаптеры всегда можно наследовать и сделать свою реализацию методов.
Кроме этой иерархии есть почти аналогичная ей. В ней содержатся адаптеры для работы с деревом – ExpandableListView. Я не буду здесь их расписывать, в целом они похожи на, уже рассмотренные, нами объекты. Но есть разница в том, что здесь данные не одноуровневые, а делятся на группы и элементы.
Здесь мы видим один готовый адаптер. SimpleExpandableListAdapter — работает с коллекциями Map.
Если вам интересны примеры работы того или иного адаптера – пишите на форуме в ветке этого урока (ссылка внизу страницы). Ближайшие несколько уроков будут посвящены этой теме.
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Источник
ListView в Android: Простое использование
Блуждал в Интернете в поисках достойного мануала. Нашел, по моему мнению, достойный, но, как водится в кругах программирования под Android он, конечно же, на английском. Вот и решил привнести свой вклад в распространение мануалов в этой среде на русском. Буду его изучать и, попутно, переводить сюда.
Напомню, что статья является переводом этой статьи с разрешения ее автора.
Продолжение статьи находится здесь. В нем рассматривается кастомизация списков и советы по их оптимизации.
Мануал написан под Android 4, Eclipse 3.7, Java 1.6. Источник можно найти здесь.
Списки — это вещь обычная в современных мобильных устройствах. Мы можем перемещаться по списку и выбирать нужный нам элемент, чтобы открыть что-то. Так и у Андроида он имеется.
ListActivity
Вы можете напрямую использовать ListView в своем проекте, как и любой другой компонент интерфейса пользователя. Если основная цель вашей Деятельности это отображение списка, то вы можете расширить класс Activity классом ListActivity, что значительно упростит использование ListView.
ListActivity расширяет Activity, чтобы упростить использование списков. Например, у вас уже будет предопределенный метод, обрабатывающий нажатие на элемент списка.
ListActivity содержит ListAdapter, ответственный за управление содержимым. Адаптер должен быть установлен в методе onCreate() вашей деятельности через метод setListAdapter().
При нажатии на элемент списка вызывается метод onListItemClick(). Этот метод позволяет получить доступ к выбранному элементу.
В Андроиде уже есть некоторые предопределенные шаблоны для использования в Адаптере, например «android.R.layout.simple_list_item1». Если же вы не хотите использовать предопределенный шаблон, ваш шаблон должен иметь идентификатор «@android:id/list», который будет называться ListView. Например:
Так же вы можете использовать вид с id «@android:id/empty». Этот вид отображается, когда список пуст.
Адаптер
Что такое Адаптер?
ListView берет содержимое для отображения через адаптер. Адаптер расширяется классом BaseAdapter и отвечает за модель данных для списка и за расположение этих данных в его элементах.
В Андроиде есть два стандартных адаптера: ArrayAdapter и CursorAdapter. ArrayAdapter управляет данными, основанными на массивах или списках, в то время, как SimpleCursorAdapter управляет содержимым из базы данных. Так же вы можете разработать свой Адаптер, расширяющий эти два класса или же класс BaseAdapter.
Самый важный метод Адаптера — getView(). Он вызывается для каждого элемента списка, чтобы определить как и какие данные должны в нем отображаться. getVew() так же содержит параметр convertView, который позволяет использовать заново уже существующий элемент списка, который уже не отображается, т.к. пользователь пролистнул его с видимой части дисплея. Если convertView не пустой, он может быть использован заново, чтобы не грузить шаблон, что приводит к значительному приросту производительности, т.к. подгрузка XML файла достаточно ресурсоемка.
ListViews и производительность
Отображение большого количества данных на мобильном устройстве должно быть реализовано максимально эффективно. Поэтому ListView создает виды (виджеты) по необходимости и подкрепляет их к иерархии видов. Стандартный Адаптер ListView удаляет виды, например, если элемент больше не отображается, он будет стерт и только его содержимое поменяется. Если вы используете свой адаптер, то вы должны так же предусмотреть это, чтобы избежать проблем с производительностью.
Пример: Простой ListActivity
Сейчас мы создадим максимально простой список. Мы используем стандартный класс Adapter — ArrayAdapter и вид, предопределенный Андроидом.
Создайте новый проект «de.vogella.android.listactivity» с Деятельностью «MyListActivity». Не изменяйте шаблон main.xml. Создайте следующую Деятельность:
Заметьте, что мы не используем setContentView(). ListActivity использует шаблон ListView по-умолчанию, если другой шаблон не задан явно.
По нажатию одного из элементов списка будет выводиться стандартный «Тост» с информацией какой из элементов был выбран.
Прошу прощения за репост. Изначально не отметил как перевод. Большое спасибо jeston за наводку, принял и научился на ошибках.
Источник