RecyclerView Adapter in Android, сделай быстрее и проще

от автора

Здравствуйте дорогие хабрчане. Это статья основана на статье, написанной в 2017 году на Java. А статью которую вы читаете, уже на Kotlin.

Каждый раз, когда мы думаем о создании RecyclerView, нас пугает объем кода, который должен войти в адаптер. Кроме того, если у этого адаптера много ViewHolder-ов, то спаси нас Бог!

Конечно, все мы знакомы с шаблонным кодом RecyclerView.Adapter. Но писать один и тот же код снова и снова — пустая трата времени.

Наверняка должен быть лучший способ?

Поздоровайтесь с FastAdapter!

Пуленепробиваемая, быстрая и простая в использовании библиотека адаптеров, которая сводит время разработки к минимуму… — Майк Пенз

FastAdapter создан Майком Пензом. Разработчик популярных библиотек, таких как MaterialDrawer и AboutLibraries.

FastAdapter сокращает время, затрачиваемое на код адаптера. Более того, он предлагает множество функций, поэтому никоим образом не ограничивает ваше приложение. Благодаря множеству предлагаемых функций подумайте о замене «обычных» адаптеров RecyclerView на FastAdapter.

Приступим к работе

Для начала использования FastAdapter-а, нужно добавить в build.gradle следующие зависимости:

Проверьте подключена ли зависимость:                    

implementation "androidx.appcompat:appcompat:${androidX}"  implementation "com.mikepenz:fastadapter:${latestFastAdapter"     implementation "androidx.recyclerview:recyclerview:1.2.1" 

Для использования  ViewBinding-а

implementation "com.mikepenz:fastadapter-extensions-binding:5.5.1"      implementation "com.mikepenz:fastadapter-extensions-diff:5.5.1"  

Не забудьте, что должен быть подключен ViewBinding

Создаем data class

Допустим, мы создаем приложение прогноза погоды. Поэтому я называю свой класс Weather.

data class Weather(     val temperature: Double,     val humidity: Int,     var windSpeed: Double,    val pressure: Double  )

Создаем xml файл weather_item.xml

<?xml version="1.0" encoding="utf-8"?>  <com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"      xmlns:app="http://schemas.android.com/apk/res-auto"      android:id="@+id/rowLayout"      android:layout_width="wrap_content"      android:layout_height="114dp"      android:layout_gravity="center"      android:layout_margin="6dp"      app:cardCornerRadius="16dp"      app:cardElevation="0dp">      <LinearLayout          android:layout_width="wrap_content"          android:layout_height="wrap_content"          android:orientation="vertical">          <TextView              android:id="@+id/temperatureTextView"              android:layout_width="wrap_content"              android:layout_height="24dp"              android:layout_gravity="center"              android:layout_marginStart="8dp"              android:layout_marginTop="12dp"              android:layout_marginEnd="8dp" />          <TextView              android:id="@+id/humidityTextView"              android:layout_width="wrap_content"              android:layout_height="24dp"              android:layout_gravity="center"              android:layout_marginStart="8dp"              android:layout_marginTop="12dp"              android:layout_marginEnd="8dp" />          <TextView              android:id="@+id/windSpeedTextView"              android:layout_width="wrap_content"              android:layout_height="24dp"              android:layout_gravity="center"              android:layout_marginStart="8dp"              android:layout_marginTop="12dp"              android:layout_marginEnd="8dp" />          <TextView              android:id="@+id/pressureTextView"              android:layout_width="wrap_content"              android:layout_height="24dp"              android:layout_gravity="center"              android:layout_marginStart="8dp"              android:layout_marginTop="12dp"              android:layout_marginEnd="8dp" />                </LinearLayout>  </com.google.android.material.card.MaterialCardView>

Внедряем адаптер

Cоздаем класс, который реализуетAbstractBindingItem

  • type() — возвращает уникальный id (вашего родительского макета)

  • bindView() — метод onBindViewHolder() RecyclerView

class WeatherItem(val weather: Weather) :

    AbstractBindingItem<WeatherItemBinding>() {

Реализовываем identifier таким образом, чтобы у каждого элемента было своё уникальное значение

override var identifier: Long          get() = weather.hashCode().toLong()          set(value) {}      override val type: Int          get() = R.id.weatherRecyclerView      override fun createBinding(          inflater: LayoutInflater,          parent: ViewGroup?      ): WeatherItemBinding {          return WeatherItemBinding.inflate(inflater, parent, false)      }      override fun bindView(binding: WeatherItemBinding, payloads: List<Any>) {          binding.temperatureTextView.text = weather.temperature.toString()          binding.humidityTextView.text = weather.humidity.toString()          binding.pressureTextView.text = weather.pressure.toString()          binding.windSpeedTextView.text = weather.windSpeed.toString()      }      override fun unbindView(binding: WeatherItemBinding) {          binding.temperatureTextView.text = null          binding.humidityTextView.text = null          binding.pressureTextView.text = null          binding.windSpeedTextView.text = null      }  }

Прикрепляем FastAdapter к нашему  RecyclerView

binding.weatherRecyclerView.setLayoutManager(              LinearLayoutManager(                  this,                  LinearLayoutManager.VERTICAL,                  false              )          )          val weatherItemAdapter = ItemAdapter<WeatherItem>()          val weatherFastAdapter =              FastAdapter.with(weatherItemAdapter)          binding.weatherRecyclerView.adapter =  weatherFastAdapter          val weatherList = weatherForecastForNextDays

map используем для  конвертации списка погоды в AbstractBindingItem      

  FastAdapterDiffUtil[weatherItemAdapter] =

            weatherList.map(::WeatherItem)

FastAdapterDiffUtil предназначен для обновления списка. Он заменяет элементы внутри адаптера новым набором элементов. Одним предложением —  меняет не весь список, а лишь те item-ы которые поменялись.

Это все, что нам нужно сделать! Если мы запустим наше приложение сейчас, мы получим RecyclerView, заполненный списком.

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

  • класс RecyclerView.Adapter

  • inflate item

  • getItemCount()

А теперь рассмотрим некоторые популярные функции RecyclerView реализованные с помощью FastAdapter:

  1. Click Listener

    weatherFastAdapter .onClickListener = { view, adapter, item, position -> // обработка клика false }

  2. Фильтрация данных с помощью поиска

    Если наше приложение использует SearchView, и мы хотим отфильтровать данные нашего адаптера, то FastAdapter может это сделать.

    weatherItemAdapter.filter("yourSearchTerm") weatherItemAdapter.itemFilter.filterPredicate = { item: WeatherItem, constraint: CharSequence? -> item.weather.temperature.toString().contains(constraint.toString(), ignoreCase = true) }

  3. Drag & Drop

    Начните с создания экземпляраSimpleSwipeDrawerDragCallback (любезно предоставленного FastAdapter-ом). Затем используйте его для инициализации ItemTouchHelper-а. Наконец, прикрепите ItemTouchHelper к RecyclerView.

touchCallback = SimpleSwipeDrawerDragCallback(  this,  ItemTouchHelper.LEFT  )  .withNotifyAllDrops(true)  .withSwipeLeft(80)  .withSensitivity(10f)  .withSurfaceThreshold(0.3f)  touchHelper =  ItemTouchHelper(touchCallback)  touchHelper.attachToRecyclerView(binding.cityListRecyclerview)

Внедрите интерфейс ItemTouchCallback. Он реализует метод itemTouchOnMove(). Добавьте к нему следующий код:

override fun itemTouchOnMove(oldPosition: Int, newPosition: Int): Boolean {  DragDropUtil.onMove(  cityWeatherItemFastAdapter.itemAdapter,  oldPosition,  newPosition  )  viewModel.changingOrderList(oldPosition, newPosition)  return true  }

Итоги

Магия RecyclerView заключается в его адаптере. FastAdapter знает это и упрощает его. Это больше, чем просто удобная библиотека. Если вы выполняете много манипуляций с адаптером, то наличие FastAdapter-а в вашем арсенале абсолютно необходимо!


ссылка на оригинал статьи https://habr.com/ru/post/599851/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *