Android studio view array

Using an ArrayAdapter with ListView

In Android development, any time we want to show a vertical list of scrollable items we will use a ListView which has data populated using an Adapter . The simplest adapter to use is called an ArrayAdapter because the adapter converts an ArrayList of objects into View items loaded into the ListView container.

The ArrayAdapter fits in between an ArrayList (data source) and the ListView (visual representation) and configures two aspects:

  • Which array to use as the data source for the list
  • How to convert any given item in the array into a corresponding View object

Note as shown above that there are other data sources besides an ArrayAdapter such as the CursorAdapter which instead binds directly to a result set from a Local SQLite Database.

When using an adapter and a ListView , we need to make sure to understand how view recycling works.

When your ListView is connected to an adapter, the adapter will instantiate rows until the ListView has been fully populated with enough items to fill the full height of the screen. At that point, no additional row items are created in memory.

Instead, as the user scrolls through the list, items that leave the screen are kept in memory for later use and then every new row that enters the screen reuses an older row kept around in memory. In this way, even for a list of 1000 items, only

7 item view rows are ever instantiated or held in memory. Here is a visual overview of recycling:

Here is another related diagram on view recycling:

Refer to this ListView guide for another look at how this works to optimize the performance of your lists. Be sure to check out this Udacity video on view recycling as well. If you wish to evaluate how fast your ListView is rendering, check out the Profiling GPU tool, which provides a graphical way of visualizing the layout performance.

To use a basic ArrayAdapter , you just need to initialize the adapter and attach the adapter to the ListView. First, we initialize the adapter:

The ArrayAdapter requires a declaration of the type of the item to be converted to a View (a String in this case) and then accepts three arguments: context (activity instance), XML item layout, and the array of data. Note that we’ve chosen simple_list_item_1.xml which is a simple TextView as the layout for each of the items.

Now, we just need to connect this adapter to a ListView to be populated:

By default, this will now convert each item in the data array into a view by calling toString on the item and then assigning the result as the value of a TextView (simple_list_item_1.xml) that is displayed as the row for that data item. If the app requires a more complex translation between item and View then we need to create a custom ArrayAdapter instead.

When we want to display a series of items from a list using a custom representation of the items, we need to use our own custom XML layout for each item. To do this, we need to create our own custom ArrayAdapter class. See this repo for the source code. First, we often need to define a model to represent the data within each list item.

Given a Java object that has certain fields defined such as a User class:

We can create a custom ListView of User objects by subclassing ArrayAdapter to describe how to translate the object into a view within that class and then using it like any other adapter.

Next, we need to create an XML layout that represents the view template for each item in res/layout/item_user.xml :

Next, we need to define the adapter to describe the process of converting the Java object to a View (in the getView method). The naive approach to this (without any view caching) looks like the following:

That adapter has a constructor and a getView() method to describe the translation between the data item and the View to display.
getView() is the method that returns the actual view used as a row within the ListView at a particular position. Another method used is getItem() which is already present in the ArrayAdapter class and its task is to simply get the data item associated with the specified position in the data set which is associated with that ArrayAdapter .

Читайте также:  Installing android from sd card

Now, we can use that adapter in the Activity to display an array of items into the ListView:

At this point, the ListView is now successfully bound to the users array data.

Once the adapter is attached, items will automatically be populated into the ListView based on the contents of the array. You can add new items to the adapter at any time with:

which will append the new items to the list. You can also clear the entire list at any time with:

Using the adapter now, you can add, remove and modify users and the items within the ListView will automatically reflect any changes.

In order to create model instances, you will likely be loading the data from an external source (i.e database or REST JSON API), so you should create two additional methods in each model to allow for construction of a list or a singular item if the data is coming from a JSON API:

For more details, check out our guide on converting JSON into a model. If you are not using a JSON source for your data, you can safely skip this step.

Within a ListView , we can easily attach event listeners onto any of the views that are item position-aware with:

You can also similarly pass an entire object through a tag as well as shown here:

With this approach, you can easily access data as needed from within any event handlers.

To improve performance, we should modify the custom adapter by applying the ViewHolder pattern which speeds up the population of the ListView considerably by caching view lookups for smoother, faster item loading:

In this example, we also have a private static class called ViewHolder . Making calls to findViewById() can be slow in practice, and if your adapter has to call it for each View in your row for every single row then you can often run into performance issues. What the ViewHolder class does is cache the call to findViewById() . Once your ListView has reached the max amount of rows it can display on a screen, Android is smart enough to begin recycling those row Views. We check if a View is recycled with if (convertView == null) . If it is not null then we have a recycled View and can just change its values, otherwise, we need to create a new row View. The magic behind this is the setTag() method which lets us attach an arbitrary object onto a View object, which is how we save the already inflated View for future reuse.

Customizing Android ListView Rows by Subclassing describes a strategy for obtaining instances of child views using a similar approach as a ViewHolder but without the explicit ViewHolder subclass.

Источник

ArrayAdapter

Создание адаптера

ArrayAdapter является простейшим адаптером, который специально предназначен для работы с элементами списка типа ListView, Spinner, GridView и им подобным. Создать адаптер этого вида можно так:

В параметрах используется контекст, XML-разметка для отдельного элемента списка и массив данных. Контекстом может быть сама активность (this), под разметкой подразумевается компонент, в котором выводится текст, например, TextView, а данными является подготовленный массив, все элементы которого по очереди вставляются в указанную разметку.

Разметку можно создать самостоятельно, а можно использовать готовую системную разметку. Если посмотреть на исходники файла simple_list_item_1.xml в документации Android SDK, то увидим, что он содержит TextView. В этом коде мы создали адаптер ArrayAdapter, в котором данные элемента TextView представлены в виде строк.

Чтобы код был более читаемым, можно сделать ещё так:

Мы вынесли массив строк в отдельную переменную.

Используем ресурсы

Если у нас есть готовый файл ресурсов (массив строк), то можно использовать специальный метод createFromResource(), который может создать ArrayAdapter из ресурсов:

Подготовим массив строк:

Теперь мы можем воспользоваться адаптером и применить к Spinner:

В этом примере мы использовали системную разметку android.R.layout.simple_spinner_item, которая тоже содержит TextView.

При использовании этого метода вы можете применять локализованные версии, что очень удобно.

Или можно пойти другим путём. Получить массив из ресурсов и вставить его в адаптер, как в самом первом примере.

Динамическое наполнение

Также мы можем создать массив программно.

ListAdapter

ListAdapter является интерфейсом. По сути ничего не меняется. Заменяем ArrayAdapter adapter на ListAdapter adapter и получаем тот же результат.

Данный интерфейс может пригодиться при создании собственного адаптера, а для стандартных случаев выгоды не вижу.

SpinnerAdapter

SpinnerAdapter также является интерфейсом и может использоваться при создании собственных адаптеров на основе ArrayAdapter. В стандартных ситуациях смысла использования его нет. Вот так будет выглядеть код:

Переопределяем адаптер

По умолчанию ArrayAdapter использует метод toString() из объекта массива, чтобы наполнять данными элемент TextView, размещённый внутри указанной разметки. Если вы используете ArrayAdapter , где в параметре используется ваш собственный класс, а не String, то можно переопределить метод toString() в вашем классе. Пример такого решения есть в конце статьи Android: Простейшая база данных. Часть вторая.

Читайте также:  Телеграм каналы для android разработчиков

Другой способ. Мы хотим выводить данные не в одно текстовое поле, а в два. Стандартная разметка для списка с одним TextView нам не подойдёт. Придётся самостоятельно создавать нужную разметку и наполнять её данными.

В этому случае нужно наследоваться от класса ArrayAdapter, указывая конкретный тип и переопределяя метод getView(), в котором указать, какие данные должны вставляться в новой разметке.

Метод getView() принимает следующие параметры: позицию элемента, в котором будет выводиться информация, компонент для отображения данных (или null), а также родительский объект ViewGroup, в котором указанный компонент поместится. Вызов метода getItem() вернёт значение из исходного массива по указанному индексу. В результате метод getView() должен вернуть экземпляр компонента, наполненный данными.

Допустим, у нас есть простой класс Cat с двумя полями — имя и пол. Нашему списку понадобится специальная разметка, состоящая из двух текстовых полей. Создадим адаптер, который будет использовать класс Cat вместо String и будем извлекать данные из объекта класса.

Как видите, достаточно просто изменить программу, используя свой класс вместо String.

В методе getView() используется не совсем корректная версия метода inflate(). Подробнее об этом читайте в статье LayoutInflater

Класс ArrayAdapter позволяет динамически изменять данные. Метод add() добавляет в конец массива новое значение. Метод insert() добавляет новое значение в указанную позицию массива. Метод remove() удаляет объект из массива. Метод clear() очистит адаптер. Метод sort() сортирует массив. После него нужно вызвать метод notifyDataSetChanged.

Несколько советов

ArrayAdapter имеет шесть конструкторов.

  • ArrayAdapter(Context context, int resource)
  • ArrayAdapter(Context context, int resource, int textViewResourceId)
  • ArrayAdapter(Context context, int resource, T[] objects)
  • ArrayAdapter(Context context, int resource, int textViewResourceId, T[] objects)
  • ArrayAdapter(Context context, int resource, List objects)
  • ArrayAdapter(Context context, int resource, int textViewResourceId, List objects)

У них у всех первые два параметра — это контекст и идентификатор ресурса для разметки. Если корневой элемент разметки является контейнером вместо TextView, то используйте параметр textViewResourceId, чтобы подсказать методу getView(), какой компонент используется для вывода текста.

Сам адаптер работает с данными, как со списками. Если вы используете стандартный массив, то адаптер переконвертирует его в список. Сами данные необязательно сразу передавать адаптеру, можно сделать это позже через метод addAll().

Другие полезные методы адаптера:

  • add() — добавляет объект в коллекцию
  • remove() — удаляет объект из коллекции
  • getItem(int position) — возвращает объект из позиции position
  • getContext() — получает контекст

На последний метод следует обратить внимание при создании собственного адаптер на основе ArrayAdapter. Не нужно в своём классе объявлять контекст таким образом.

Через метод getContext() вы уже можете получить доступ к контексту, не объявляя новой переменной.

Тоже самое применимо и к массивам. Не нужно объявлять массив:

Используйте метод getItem(position), который может получить доступ к массиву.

Если позволяет логика, используйте списки вместо массивов для большей гибкости. Тогда вы можете добавлять и удалять данные через методы add() и remove().

Источник

Введение

Одна из частых задач, возникающих при программировании Android приложений, — это отображение на дисплее набора данных. Например, списка пользователей, содержимого папки, набора заметок и так далее. Для решения данной задачи в составе Android SDK есть такие компоненты как ListView, GridView, RecyclerView. В этой статье речь пойдет об использовании ListView. Этот компонент на данный момент является самым распространенным.

Итак, ListView предназначен для отображения набора данных в виде одномерного (в один столбец) списка. Принцип работы данного компонента состоит в том, что он создает несколько View элементов, достаточных для отображения видимой части списка и затем переиспользует их (то есть заполняет новыми данными), когда пользователь скролит список.

Созданием View элементов списка и заполнением их данными занимается адаптер — объект, который реализует интерфейс Adapter. Он создается разработчиком на этапе конфигурирования ListView. В составе Android SDK уже есть несколько готовых адаптеров, работающих «из коробки», например ArrayAdapter, SimpleAdapter, CursorAdapter. Также разработчик может написать свой, так называемый custom адаптер, что обычно и приходится делать.

Базовая схема использования ListView выглядит так:

  • прописываем ListView в требуемый layout файл Activity или Fragment
  • создаем объект для хранения данных и заполняем его данными
  • создаем layout для одного элемента списка
  • создаем адаптер, передав ему набор данных и layout одного элемента списка
  • получаем ссылку на ListView и передаем ему адаптер
  • добавляем обработчики событий, например OnItemClickListener

Попробуем написать простое приложение с ListView и ArrayAdapter.

ListView и ArrayAdapter

1. Создаем в Android Studio проект на базе шаблона EmptyActivity.

File > New > New Project. далее следуем указаниям визарда.

Я создал проект с такими параметрами:

  • Application name: ListViewTest1
  • Company Domain: codeandlife.ru
  • Platforms: Phone and Tablet — API15:Android4.0.3 (IceCreamSandwich)
  • Template: EmptyActivity
Читайте также:  Tablayout android studio example

2. В layout файл Activity добавляем ListView.

По умолчанию AndroidStudio создает файл разметки с RelativeLayout и TextView. Меняем RelativeLayout на FrameLayout, а TextView на ListView. Должен получиться примерно такой код:

id нужен для того чтобы получить ссылку на ListView в коде.

layout_width и layout_height задают размеры Listview. В данном случае ListView займет все пространство, которое ему предоставит FrameLayout.

3. Создаем объект для хранения данных и заполняем его.

Тип объекта, используемого для хранения данных, определяется типом используемого адаптера. ArrayAdapter может работать с массивами или коллекциями, реализующими List интерфейс. Если разработчик создает свой адаптер, он может использовать произвольные объекты, например xml файл.

Мы будем использовать ArrayList и набор строк. Код будет выглядеть так:

Замечание! На этапе создания адаптера и конфигурирования ListView, данные для отображения могут отсутствовать, например, если они подгружаются из базы данных или удаленного веб-сервиса. В этом нет ничего необычного, их можно добавить и потом. Этот момент будет разобран в следующих статьях.

4. Создаем layout одного элемента списка.

Для этого в AndroidStudio нажимаем правой кнопкой мыши на папке res > layout и создаем новый Layout resource file.

ArrayAdapter умеет работать только с макетами, в которых есть только одно текстовое поле для заполнения. Обычно это TextView. В макете могут присутствовать другие View элементы, но ArrayAdapter не сможет ничего с ними сделать.

Наш макет будет выглядеть так:

id нужен для того, чтобы адаптер мог получить ссылку на TextView (хотя если макет состоит из одного TextView, то этот параметр можно опустить)

layout_with и layout_height задают размеры TextView. В данном случае он растянется по горизонтали на всю ширину, предоставленную родительским компонентом (ListView), а по высоте будет равен высоте текста + padding параметр.

padding – задается в dp (density-independent pixel) единицах и представляет собой пространство между текстом и внешней границей TextView

textSize – определяет размер текста и задается в sp (scale-independent pixel) единицах

Замечание! Android SDK имеет собственный набор ресурсов (картинки, макеты, наборы цветов и так далее), которые разработчик может использовать в своих приложениях. В данном случае мы могли бы применить готовый макет android.R.layout.simple_list_item_1, который имеет такую же структуру — один TextView.

5. Создаем адаптер и передаем его ListView.

Адаптер — это объект, создающий View объект на основе переданного ему layout файла и заполняющий этот объект данными. В этой роли может выступать класс, который реализует интерфейс Adapter. Для упрощения задачи, мы используем готовый класс адаптера — ArrayAdapter. Это самый простой адаптер в Android SDK, поэтому с него и стоит начать знакомство.

Класс ArrayAdapter имеет несколько конструкторов, нам подойдут вот такие:

context – это объект, который используется адаптером для создания View объектов на основе переданного макета. Обычно здесь передается ссылка на Activity.

resource – это id макета элемента списка, то есть id layout файла.

textViewResouceId – id элемента, отображающего текст. В нашем случае это id TextView.

objects – ссылка на коллекцию, содержащую данные

Если layout элемента списка состоит только из TextView (как в нашем случае), достаточно первого конструктора. Если layout более сложный (из нескольких View объектов), нужно использовать второй конструктор и передавать адаптеру id текстового поля.

В нашем случае код будет выглядеть так:

6. Получаем ссылку на ListView и передаем ему адаптер.

Тут все просто, ссылку на View объект в Activity мы получаем с помощью метода findViewById(int id).

Все. С этого момента ListView уже будет работать. Можно загрузить приложение в телефон или эмулятор и убедиться в этом.

7. Добавляем обработчики нажатий — listener объекты.

Имея ссылку на ListView, разработчик может назначить ему обработчики событий. Наиболее часто используемые события — это кратковременное нажатие на элемент списка и длительное нажатие. Для регистрации обработчиков этих событий используются следующие методы:

Эти методы принимают ссылки на объекты, реализующие интерфейсы OnItemClickListener и OnItemLongClickListener. Каждый интерфейс содержит по одному методы, которые будут вызываться ListView при наступлении соответствующего события. Для интерфейса OnItemClickListener метод выглядит так:

parent – ссылка на ListVew

view – ссылка на view объект, на который было произведено нажатие.

position – позиция view в адаптере

id – идентификационный номер элемента списка, обычно совпадает с position.

Самый простой вариант добавления обработчика состоит в использовании анонимного класса. Вот так:

Многие разработчики не любят подобное нагромождение кода и предпочитают реализовать требуемый интерфейс в Activity (или Fragment) и передавать ссылку на нее. Вот так:

В обработчике события обычно выполняется какая-либо работа с нажатым View или данными, соответствующими этому элементу списка. Получить данные из обработчика можно несколькими способами. Самый простой способ состоит в использовании ссылки на объект, в котором хранит данные. В нашем случае это ссылка на ArrayList.

Также можно получить данные, использую объект parent, который передается обработчику. На мой взгляд — это более правильный способ доступа к данным.

Источник

Оцените статью