Как использовать recyclerview-selection, задав ключ в виде строки? - PullRequest
0 голосов
/ 23 июня 2019

Используя библиотеку Android androidx.recyclerview.selection, я попытался реализовать множественный выбор в RecyclerView, следуя инструкциям здесь и здесь .

Но я хочу, чтобы мой key был String вместо Long, но я сталкиваюсь с двумя ошибками:

tracker = SelectionTracker.Builder<String>(
    "selection_id",
    recyclerView,
    StableIdKeyProvider(recyclerView),    // this line shows error
    MyItemDetailsLookup(recyclerView),
    StorageStrategy.createStringStorage()    // this line shows error
    ).withSelectionPredicate(
        SelectionPredicates.createSelectAnything()
    ).build()

Мне нужны некоторые подробности о том, как ItemKeyProvider реализован для String, а во-вторых,

StorageStrategy.createStringStorage() // this shows error
StorageStrategy.createLongStorage()   // this doesn't show error

почему это происходит, когда везде я заменил универсальный тип с Long на String?

1 Ответ

0 голосов
/ 25 июня 2019

Согласно документам , StorageStrategy используется для хранения ключей в сохраненном состоянии,

/* for    Long    keys */    StorageStrategy.createLongStorage()
/* for   String   keys */    StorageStrategy.createStringStorage()
/* for Parcelable keys */    StorageStrategy.createParcelableStorage(Class)

Также, согласно документам , StableIdKeyProvider предусматривает ключи типа Long. Вот почему ваш StorageStrategy показывает ошибку, потому что ожидает Long ключей.

Чтобы предоставить String ключи, вы должны создать свой собственный класс ItemKeyProvider. Для получения более подробной информации о ItemKeyProvider, вы можете обратиться к документам здесь.

Вот как вы можете реализовать ItemKeyProvider класс для String ключей:

class MyItemKeyProvider(private val rvAdapter: MyAdapter): ItemKeyProvider<String>(SCOPE_CACHED) {
    override fun getKey(position: Int): String = rvAdapter.getItem(position).myKey
    override fun getPosition(key: String): Int = rvAdapter.getPosition(key)
}

и MyAdapter:

class MyAdapter(private val myList: ArrayList<MyModel>): RecyclerView.Adapter<MyAdapter.MyViewHolder>() {
    // functions used in MyItemKeyProvider
    fun getItem(position: Int) = myList[position]
    fun getPosition(key: String) = myList.indexOfFirst { it.myKey == key }

    // other functions
}

где MyModel примерно так:

data class MyModel (
    val myKey: String,
    // other data
)

Теперь вы можете просто построить свой SelectionTracker так:

myTracker = SelectionTracker.Builder(
        "my_selection_id",
        recyclerView,
        MyItemKeyProvider(rvAdapter),
        MyItemDetailsLookup(recyclerView),
        StorageStrategy.createStringStorage()
    ).withSelectionPredicate(
        SelectionPredicates.createSelectAnything()
    ).build()

Обратите внимание, что вы не должны писать следующий код в Adapter, если вы не используете StableIdKeyProvider:

init { setHasStableIds(true) }

в противном случае будет отображаться эта ошибка:

Attempt to invoke virtual method 'boolean androidx.recyclerview.widget.RecyclerView$ViewHolder.shouldIgnore()' on a null object reference

В этом руководстве показано, как реализовать recyclerview-selection с помощью Long ключей, а также показано, как реализовать собственный класс ItemKeyProvider для Long ключей.

Чтобы реализовать recyclerview-selection с помощью Parcelable ключей, я нашел пример кода здесь .

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