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/


Интересные статьи

Интересные статьи

Как минимизировать эффект кривой забывания и другие методы запоминания полезной информации.
Как безопасно и без лишнего труда открыть доступ к этим учетным данным и использовать их при разработке на Node.js? Ответу на этот вопрос посвящена эта статья.Содержание:Подключение к экземпляру Kafka...
Как-то раз мне нужно было создать собственный ItemDecoration, и я обнаружил, что в Интернете. почти нет ответов на этот вопрос. Надеюсь, что эта стать будет кому-нибудь п...
Пока писал эту сугубо техническую статью, Хабр успел превратиться в местное отделение ВОЗ и теперь мне даже стыдно ее публиковать… но в душе теплится надежда, что айтишники еще не разбежались и о...
Сравнивать CRM системы – дело неблагодарное. Очень уж сильно они отличаются в целях создания, реализации, в деталях.