У меня возникла хитрая проблема с фильтрацией коллекций в kotlin ...
У меня есть базовый класс, который управляет списком элементов, и я хочу иметь возможность фильтровать список по ключевому слову, чтобы я расширен класс с помощью методов Filterable.
Я хочу иметь возможность расширять несколько классов с помощью этого «базового класса», чтобы механизм фильтрации был одинаковым для всех классов.
Эти классы не имеют одинаковых свойств ... В одном из них фильтрация должна происходить в зависимости от того, найдено ли ключевое слово в имени, а в другом классе фильтрация выполняется в свойстве комментария.
Вот некоторый код:
data class ProductInfo(): {
var _name: String
var name: String
get() = _name
set(value) { _name = value }
}
abstract class BaseFirestoreAdapter<T : BaseFirestoreAdapter.DataInterface, VH : RecyclerView.ViewHolder> : RecyclerView.Adapter<VH>(), Filterable
{
var sourceList: MutableList<ProductInfo> = ArrayList()
...
override fun performFiltering(keyword: CharSequence): FilterResults {
val keywordRegex = keyword.toString().toRegex(setOf(RegexOption.IGNORE_CASE, RegexOption.LITERAL))
filteredList = sourceList.filter {
keywordRegex.containsMatchIn(Normalizer.normalize(it.name, Normalizer.Form.NFD).replace("[^\\p{ASCII}]".toRegex(RegexOption.IGNORE_CASE), ""))
}
results.values = filteredList.sortedWith(orderComparator)
results.count = filteredList.size
}
...
}
Я разработал «базовый класс», чтобы он работал с первым классом, упомянутым выше (фильтрация выполняется с помощью «it.name»), и он работает, но теперь, когда я пытаясь сделать его обобщенным c (T), чтобы использовать его со вторым классом (комментарии), я не могу найти способ сделать это ...
Я думал, что смогу передать предикат, связанный с классом определение того, как сопоставить предметы дурина Принимая во внимание фильтрацию, но поскольку ключевое слово известно только в методе executeFiltering, я не могу правильно создать предикат вне этого метода ...
У меня сейчас немного идей! lol
У кого-нибудь из вас есть идея?
ОБНОВЛЕНИЕ : Следуя предложению @ Tenfour04, я попытался адаптировать его к своему коду, который передает предикаты фильтрации через метод вместо использования конструктора, но он не компилируется, если я не заменю «ActivyInfo :: comments» на что-то вроде «ActivyInfo :: comments.name», но тогда значение, которое я получаю для «seekProperty (it)» в отладке, равно «name», которое не является значением комментария.
Вот код:
CommentAdapter:
override fun getFilter(): Filter {
super.setFilter(
{ it.state != ProductState.HIDDEN },
{ ActivyInfo::comments },
compareBy<ProductInfo> { it.state }.thenBy(String.CASE_INSENSITIVE_ORDER) { it.name })
return super.getFilter()
}
BaseAdapter:
lateinit var defaultFilterPredicate : (T) -> Boolean
lateinit var searchedProperty : (T) -> CharSequence
lateinit var orderComparator : Comparator<T>
fun setFilter(defaultPredicate: (T) -> Boolean, property: (T) -> CharSequence, comparator: Comparator<T> ) {
defaultFilterPredicate = defaultPredicate
searchedProperty = property
orderComparator = comparator
}
override fun performFiltering(constraint: CharSequence): FilterResults {
...
filteredList = sourceList.filter {
constraintRegex.containsMatchIn(Normalizer.normalize(searchedProperty(it), Normalizer.Form.NFD).replace("[^\\p{ASCII}]".toRegex(RegexOption.IGNORE_CASE), ""))
}
...
}