Адаптеры
В 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.
На сайте представлены (будут представлены) практически все примеры с адаптерами. Оставайтесь на связи!
Источник
Адаптеры и списки
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() .
Источник
Полный список
— разбираемся в адаптерах
На последних уроках мы использовали адаптеры и сейчас вполне можем сформулировать, что это такое. Адаптер – мост между набором данных и объектом, использующим эти данные. Также адаптер отвечает за создание 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 для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Источник
Зачем нужен адаптер в Android?
Почитываю тут про Android и не понимаю, зачем нужны адаптеры? Т.е. я понимаю что он связывает данные и объекты, но какая практическая надобность?
Вот нужно мне вывести список с иконками, каким-то текстом и прочими данными. Делаю отдельный layout (xml), беру inflater и циклом вывожу всё что нужно.
Да, тоже самое можно сделать и через адаптеры, но не понимаю зачем? Просто как альтернативный способ вывода данных?
- Вопрос задан более трёх лет назад
- 1537 просмотров
Inflater используется чтобы просто получить из XML-файла View’шку в виде объекта.
Adapter списка используется, чтобы обрабатывать данные для вывода их в список.
У них разные области применения.
Зачем вам мучить и себя и систему тем, чем в Android’е уже давно озаботились?
Вы можете в своем адаптере получить view при помощи inflater’а и единожды показав, что и куда из данных надо поставить получить полноценный список с преферансом и куртизанками, вместо простого списка view, который вы хотели получить циклом.
Возможно мне просто стоит ещё раз перечитать про них по отдельности. Потому как сейчас по прежнему не очень понимаю сути. Inflater даст вьюшку в виде объекта. Окей, взяли объект, заполнили, и проделали необходимое с кучей подобных объектов и показали. Или всё не так?
Если вас не затруднит, напишите пример (не кусок кода, а на слониках или яблоках).
Семён Семёнов, можно и так, но в таком случае у вас будет просто большое кол-во view, без нормальной возможности контроля.
Списки же дают вам возможность контролировать и данные и их вывод.
Удалили элемент списка где-то в центре или добавили еще один — вызвав один метод на обновление UI получился снова полноценный список, с кучей вьюшек вам придется самим запариваться над их контролем. Списки и адаптеры просто убрали множество возможных проблем.
Скажем, список почты. При использовании кучи View очень не удобно будет изменять этот список, вести общий контроль, а ведь это необходимые возможности, пользователь захотел удалить письмо, все что вам надо это удалить его из списка, вызвать notifyItemChanged и все, всю остальную работу за вас выполнит адаптер.
Константин Довнар: Да, теперь я понял. Inflater позволит мне просто отобразить данные, адаптер же — с ними ещё и работать. Inflater может подойти для того, что не будет меняться, всегда в одном количестве. Например, для какого-то меню или типа того.
Источник