Размер
Урок 11. Работа с RecyclerView на примере TweetsRecyclerView
Play

Урок 11. Работа с RecyclerView на примере TweetsRecyclerView

Добавление разделителя информации о пользователе и списка твитов

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

Видим, что нам необходимо добавить View серого цвета после информации о пользователе и разместить под ней список RecyclerView . Мы бы могли поместить эту View просто под последним TextView , но View должна занимать всю ширину. Это трудно сделать потому что у RelativeLayout установлено свойство padding , которое делает отступ перед всеми вложенными элементами. Поэтому сделаем LinearLayout корневым элементом нашего layout , в свою очередь у него будет 3 вложенных элемента:

  • RelativeLayout с информацией о пользователе. Тот контейнер, который до этого момента являлся корневым.
  • View – разделитель информации.
  • RecyclerView – список твитов, который мы добавим чуть позже в этом уроке.

Наш layout после этих преобразований выглядит так:

Наш RelativeLayout практически не изменился. Единственное что мы изменили – поменяли значения атрибута android:layout_height c match_parent на wrap_content . Это необходимо, чтобы нашему разделителю хватило места на экране.

Мы просто сделали корневым элементом LinearLayout и добавили нашу View в качестве элемента, который находится под RelativeLayout .

Знакомство с элементом RecyclerView

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

Напомним, что в 7 уроке мы уже создали с вами файл tweet_item_view . В этом занятии мы просто свяжем его с java кодом, чтобы динамически добавлять во View информацию.

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

Вначале надо добавить строку implementation 'com.android.support:recyclerview-v7:26.1.0' в файл build.gradle , чтобы иметь доступ в коде к RecyclerView .

Далее добавим наш RecyclerView в layout файл. Не будем добавлять никаких зависимостей от соседних элементов, т.к. его родителем является LinearLayout . Просто поместим его после нашей View разделителя. И свяжем его с элементом в java коде.

В Activity мы создали отдельный метод initRecyclerView() , который вызываем в методе onCreate() .

Для работы с RecyclerView необходим LayoutManager , а также Adapter . LayoutManager отвечает за форму отображения элементов: обычная линейная, в виде сетки, в виде шахматной сетки. В данном случае нам нужен обычный линейный список, поэтому используем LinearLayoutManager :

Если вы сейчас запустите приложение, то увидите, что ничего визуально не изменилось. Это потому что список пуст. Чтобы в нём была какая-то информация его надо заполнить элементами. Для этого нам понадобится класс Adapter (переходник) – класс, который отвечает за связь элементов java кода с View -компонентами. Т.е. получая набор java объектов, мы должны подать его на вход в адаптер, который преобразует его уже в набор View -компонентов, которые и использует в дальнейшем RecyclerView .

Давайте создадим новый пакет adapter , где и разместим класс TweetAdapter . Вспоминаем, что надо нажать по пакету colibri.dev.com.colibritweet правой кнопкой и выбрать New -> Package . После этого вводим имя adapter .

После этого в этом пакете создаём новый java класс ( New -> Java class ), который называем TweetAdapter . Выглядеть результат должен так:

Работа с TweetAdapter

Adapter , используемый при работе с RecyclerView обязан определить объект типа ViewHolder , который предоставляет доступ ко всем View -компонентам в каждой строке списка. Давайте модифицируем наш адаптер, добавив необходимые для RecyclerView зависимости:

Теперь, когда мы определили базовый адаптер и ViewHolder , нам нужно заполнить наш адаптер. Сначала давайте создадим переменную для списка твитов:

Для того, чтобы работа с нашим адаптером была гибкой, нам нужны какие-то рычаги для управления наполнением адаптера. Давайте добавим два метода для этого. Один будет служить для наполнения коллекции, другой – для очистки, если нам понадобится обновить информацию на экране:

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

Каждый адаптер должен реализовывать 3 главных метода:

  • onCreateViewHolder(ViewGroup parent, int viewType) – метод вызывается для создания объекта ViewHolder , в конструктор которого необходимо передать созданный View -компонент, с которым в дальнейшем будут связываться java объекты. Метод вызывается без нашего личного вмешательства, т.к. RecyclerView в себе инкапсулирует логику переиспользования элементов;
  • onBindViewHolder(TweetViewHolder holder, int position) – этот метод отвечает за связь java объекта и View . Метод также вызывается без нашего участия. Он будет вызываться чаще, чем метод onCreateViewHolder из-за того, что View компоненты будут переиспользоваться и в один и тот же визуальный элемент в процессе жизнедеятельности списка будут устанавливаться разные данные;
  • getItemCount() – сообщает количество элементов в списке.

Давайте реализуем их:

Отлично, теперь осталось добавить код, который будет заполнять данными наши View -компоненты в TweetViewHolder :

Всё, что делает данный код – используя ранее созданные View -компоненты, он заполняет их новыми данными. Таким образом происходит переиспользование View -компонентов без лишнего создания новых. Именно с этим связана следующая строка кода метода bind нашего TweetViewHolder :

Если бы переиспользования элементов не было, то достаточно было бы написать строку:

Но из-за того, что наши элементы переиспользуются, то один раз скрыв изображение на одном элементе, оно будет скрыто на нём и при повторном использовании. Даже в том случае, если оно должно быть показано. Это нас не устраивает.

Также давайте подробнее остановимся на методе форматирования даты, использующегося при заполнении данными нашего компонента:

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

Константа TWITTER_RESPONSE_FORMAT представляет собой формат, в котором мы получим дату от Twitter-сервиса. Такую дату отображать пользователю было бы странно. Нас больше устроил бы более простой вариант MONTH_DAY_FORMAT , когда мы отображаем только месяц и день.

Метод String getFormattedDate(String rawDate) принимает на вход дату в формате, в котором мы получим её от сервиса. На выходе же мы получаем готовую к использованию строку даты.

Для начала нам необходимо из строк шаблонов создать java объекты SimpleDateFormat , при помощи которых мы и будем производить преобразования. Т.к. напрямую строку даты одного формата в строку другого формата преобразовать мы не можем, то нам нужен переходный элемент:

Данной операцией мы преобразовали строку, пришедшую нам от сервиса Twitter, в соответствии с шаблоном к обычном java объекту Date , которым теперь можно манипулировать каким угодно образом. Нам остаётся просто отформатировать вновь созданный объект даты в соответствии с необходимым нам шаблоном:

Добавление TweetAdapter к списку RecyclerView

Вот и всё, теперь осталось только сказать нашему RecyclerView , что за наполнение элементов в нём отвечает созданный нами адаптер. Достаточно добавить следующий код в UserInfoActivity :

Теперь давайте убедимся, что наш список действительно работает. Для этого:

  • создадим метод Collection<Tweet> getTweets() , который будет возвращать нам коллекцию объектов-заглушек.
  • создадим метод loadTweets() , где вызовём метод getTweets() и отобразим результат в экземпляре TweetAdapter .

Теперь давайте запустим наше приложение и посмотрим, что получилось.

Отличная работа. Подытожим всё вышесказанное схемой, которая используется в официальной документации для отображения принципа работы c RecyclerView :

В этой схеме чётко разграничены 3 слоя: View -слой – это непосредственно сам RecyclerView , а также его «помощник» LayoutManager , который отвечает за форму отображения элементов. Dataset – это данные, которые необходимо отобразить в списке. Могут быть представлены в любом виде: как в нашем случае – методом-заглушкой или реально запрашиваемыми с сервера данными, как мы это сделаем в следующих уроках. * Adapter представляет собой натуральный переходник между сырыми данными и пользовательским интерфейсом, готовым к их отображению.

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

По итогу этого урока мы полностью подготовили наш экран списка твитов для их просмотра. Осталось только получить их.

На всякий случай отобразим полный листинг кода UserInfoActivity и TweetAdapter :

📎📎📎📎📎📎📎📎📎📎