你的支持对我意义重大!
🔥 Hi,我是小彭。本文已收录到 GitHub · Android-NoteBook 中。这里有 Android 进阶成长路线笔记 & 博客,有志同道合的朋友,欢迎跟着我一起成长。(联系方式在 GitHub)
我们先说一种我们很熟悉的 PC 列表样式,列表底部会带有 上一页/ 下一页 / 页码
的页码切换功能,比如淘宝、百度、京东等列表。这类样式最大的特点是浏览的节奏感,在用户浏览一页数据后会有停顿,因此列表底部常常会设置相关推荐、猜你喜欢等功能。
传统 PC 列表对屏幕尺寸有一定要求,因此在手机端很少见。那么手机端有哪些常见的列表样式呢?从数据是否有尽头,可以分为普通列表和瀑布流列表。
普通列表是相对于瀑布流列表的,普通列表的内容是有限的,只要一直滑总能滑到尽头。从单个数据项的设计样式区分,可以分为纯文字、图文混排、卡片三种:
相对于简单列表,瀑布流列表指内容像瀑布一样源源不断,一直滑不到尽头的列表。最常见的一种瀑布流是信息流(或 Feed 流),几乎每个产品都存在信息流。信息流在分发内容时,会根据用户的喜好对内容进行干预,更精准地向用户推荐内容。我们熟悉的产品中有哪些是信息流呢?
即使列表的数据量很小,列表接口也应该在一开始就支持分页增量请求,避免将来再支持时的兼容问题。那么,列表分页有哪些设计方案呢?
基于偏移是最常见的分页接口设计,其原理是通过数据库查询语句的 offset + limit 指定某一分页的数据。例如:
# 获取第 curPage 页数据,每页数据量为 pageSize select * from ... where ... order by ... limit (curPage - 1) * pageSize, pageSize
因此,前端参数需要指定请求的页码 page 和可选的每页数据量 size:
第一页请求: page : 1 // 当前页码,必选 size : 10 // 每页数据量,可选 响应: list:[{1},{2},{3}...,{10}] // 列表数据 total:100 // 数据总量 ----------------------------------- 第二页请求: page : 2 // 当前页码,必选 size : 10 // 每页数据量,可选 响应: list:[{11},{12},{13}...,{20}] // 列表数据 total:100 // 数据总量
基于偏移的分页方案优势在于简单易理解,而且能够支持点击 上一页/ 下一页 / 页码
按钮切换分页,实现传统 PC 列表的样式。但劣势也是很明显的,主要分为两个方面:
数据重复的情况虽然可以通过前端去重的方式避免,但也会导致新一页展现的数据量参差不齐。那么,对于动态数据的场景,应该如何设计分页接口呢?
基于游标的分页设计适用于动态数据场景,其原理是根据已获取的最后一条数据的 ID 作为参数来请求下一页数据。例如:
# 获取第 curCursor 后的一页数据,每页数据量为 pageSize select * from ... where ... and id > $curCursor order by id limit ($curPage - 1) * $pageSize, $pageSize
因此,前端在请求分页接口时,不再指定下一个页码 page,而是根据已接收的最后一条数据的 ID 来请求下一页数据:
第一页请求: cursor : 0 // 当前游标,必选 size : 10 // 每页数据量,可选 响应: list:[{1},{2},{3}...,{10}] // 列表数据 total:100 // 数据总量 ----------------------------------- 第二页请求: cursor : 10 // 当前游标,必选 size : 10 // 每页数据量,可选 响应: list:[{11},{12},{13}...,{20}] // 列表数据 total:100 // 数据总量
为什么游标的方案可以避免数据重复或缺失呢?这是因为无论数据发生新增还是减少时,基于游标的分页请求都获取该游标后续的一页数据,而基于偏移的分页请求是获取变更后数据排序后指定偏移位置的数据,这些数据在之前的请求中是否重复或缺失是无从得知的。
当然了,基于游标的分页方案也存在局限性:
上一页/ 下一页 / 页码
按钮切换分页,App 基本不存在传统 PC 列表的操作,几乎没有影响;你的点赞对我意义重大!希望大家可以一起讨论技术,找到志同道合的朋友,我们下次见!