Будешь ли использовать пейджинг по дате сообщений или количеству сообщений

Ответ

Лучше использовать пейджинг по дате, так как он более предсказуем для пользователя и лучше работает с бесконечной лентой. При пейджинге по количеству могут возникать проблемы при изменении данных (удаление/добавление сообщений), что приведёт к дублированию или пропуску контента.

Пример реализации на Kotlin с Paging 3:

class MessagesPagingSource : PagingSource<Long, Message>() {
    override suspend fun load(params: LoadParams<Long>): LoadResult<Long, Message> {
        val beforeTime = params.key ?: System.currentTimeMillis()
        val messages = api.getMessages(beforeTime, params.loadSize)
        return LoadResult.Page(
            data = messages,
            prevKey = null, // только вперед
            nextKey = messages.lastOrNull()?.timestamp
        )
    }
}

Ответ 18+ 🔞

А, ну это же классика, ёпта! Смотри, тут история как с пивом в холодильнике — кажется, логично по количеству считать, а на деле пиздец какой.

Представь: у тебя лента сообщений, ты листаешь по 20 штук. Только что пролистал, вернулся наверх — бац, а там новое сообщение вклинилось. И поехала вся нумерация к чертям собачьим! Теперь у тебя 21-е сообщение стало 20-м, а то, что ты уже видел, съехало ниже. Листаешь дальше — оп, дубль! Одно и то же сообщение второй раз вылезло, потому что сместилось в следующую пачку. Вообще пиздец, волнение ебать, терпения ноль ебать.

А вот пейджинг по дате — это как хороший русский мужик, предсказуемый. Не важно, что там в середине добавили или удалили. Ты листаешь "покажи мне всё, что было до 5 марта". Получил. Потом "а теперь что было до 1 марта". И никаких сюрпризов! Даже если между этими датами десять новых сообщений влезло — они просто в следующую пачку попадут, когда ты до них долистаешь. Красота!

Смотри, как это на Kotlin с Paging 3 выглядит — проще пареной репы:

class MessagesPagingSource : PagingSource<Long, Message>() {
    override suspend fun load(params: LoadParams<Long>): LoadResult<Long, Message> {
        val beforeTime = params.key ?: System.currentTimeMillis()
        val messages = api.getMessages(beforeTime, params.loadSize)
        return LoadResult.Page(
            data = messages,
            prevKey = null, // только вперед
            nextKey = messages.lastOrNull()?.timestamp
        )
    }
}

Видишь? Берём время "до какого момента показывать", грузим пачку, и следующий ключ — это время последнего сообщения в этой пачке. Всё, блядь, элементарно! Листаешь себе спокойно, как будто на дворе 2002-й год и интернет по карточкам, никаких неожиданностей.

А то с количеством — чистая лотерея. Сегодня работает, завтра какой-нибудь юзер удалит своё сообщение — и пошла плясать вся логика. Сам от себя охуеешь, когда в продакшене такое вылезет. Так что не мудри — дата рулит, пизда рулю!