Я был в том же месте, что и вы, и придумал это решение.
Одно важное замечание: для реализации этого мне пришлось изменить свой конвертер дат в базе данных, с длинного на строковоечтобы сохранить временную метку
это мои конвертеры
class DateConverter {
companion object {
@JvmStatic
val formatter = SimpleDateFormat("yyyyMMddHHmmss", Locale.ENGLISH)
@TypeConverter
@JvmStatic
fun toDate(text: String): Date = formatter.parse(text)
@TypeConverter
@JvmStatic
fun toText(date: Date): String = formatter.format(date)
}
}
Некоторые начальные данные, хотя у меня есть список заголовков отчетов, которые я хочу показать, пролистать и иметь возможность фильтровать
Они представлены этим объектом:
data class ReportHeaderEntity(
@ColumnInfo(name = "id") override val id: UUID
, @ColumnInfo(name = "name") override val name: String
, @ColumnInfo(name = "description") override val description: String
, @ColumnInfo(name = "created") override val date: Date)
Я также хотел добавить разделители между элементами в списке, чтобы показать их по дате
Я достиг этого, выполнивследующее:
Я создал новый запрос в комнате, как этот
@Query(
"SELECT id, name, description,created " +
"FROM (SELECT id, name, description, created, created AS sort " +
" FROM reports " +
" WHERE :filter = '' " +
" OR name LIKE '%' || :filter || '%' " +
" OR description LIKE '%' || :filter || '%' " +
" UNION " +
" SELECT '00000000-0000-0000-0000-000000000000' as id, Substr(created, 0, 9) as name, '' as description, Substr(created, 0, 9) || '000000' AS created, Substr(created, 0, 9) || '256060' AS sort " +
" FROM reports " +
" WHERE :filter = '' " +
" OR name LIKE '%' || :filter || '%' " +
" OR description LIKE '%' || :filter || '%' " +
" GROUP BY Substr(created, 0, 9)) " +
"ORDER BY sort DESC ")
fun loadReportHeaders(filter: String = ""): DataSource.Factory<Int, ReportHeaderEntity>
Это в основном создает разделительную линию для всех элементов, которые я отфильтровал через
, он также создаетфиктивная дата для сортировки (со временем 25:60:60, чтобы она всегда появлялась перед остальными отчетами)
Затем я объединяю это со своим списком, используя объединение, и сортирую их по фиктивной дате
Причина, по которой мне пришлось перейти с long на string, заключается в том, что гораздо проще создать фиктивные даты со строкой в sql и отделить часть даты от всего времени даты
Выше приведен список, подобный следующему:
00000000-0000-0000-0000-000000000000 20190522 20190522000000
e3b8fbe5-b8ce-4353-b85d-8a1160f51bac name 16769 description 93396 20190522141926
6779fbea-f840-4859-a9a1-b34b7e6520be name 86082 description 21138 20190522141925
00000000-0000-0000-0000-000000000000 20190521 20190521000000
6efa201f-d618-4819-bae1-5a0e907ddcfb name 9702 description 84139 20190521103247
В моем PagedListAdapter я изменил его на реализацию PagedListAdapter<ReportHeader, RecyclerView.ViewHolder>
(не определенный видоискатель)
Добавлен в объект-компаньон:
companion object {
private val EMPTY_ID = UUID(0L,0L)
private const val LABEL = 0
private const val HEADER = 1
}
и переопределить получить тип представления следующим образом:
override fun getItemViewType(position: Int): Int = if (getItem(position)?.id ?: EMPTY_ID == EMPTY_ID) LABEL else HEADER
Затем я создал два отдельных держателя вида:
class ReportHeaderViewHolder(val binding: ListItemReportBinding) : RecyclerView.ViewHolder(binding.root)
class ReportLabelViewHolder(val binding: ListItemReportLabelBinding) : RecyclerView.ViewHolder(binding.root)
и реализовал другие переопределенные методы следующим образом:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val inflater = LayoutInflater.from(parent.context)
return when (viewType) {
HEADER -> ReportHeaderViewHolder(DataBindingUtil.inflate(inflater, R.layout.list_item_report, parent, false))
else -> ReportLabelViewHolder(DataBindingUtil.inflate(inflater, R.layout.list_item_report_label, parent, false))
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val reportItem = getItem(position)
when (getItemViewType(position)) {
HEADER -> {
(holder as ReportHeaderViewHolder).binding.apply {
report = reportItem
executePendingBindings()
}
}
LABEL -> {
(holder as ReportLabelViewHolder).binding.apply {
date = reportItem?.name
executePendingBindings()
}
}
}
}
Я надеюсь, что это помогает и вдохновляет людей находить еще лучшие решения