漫画阅读器的断点续读:进度、书签与同步的取舍
合上阅读器,隔天再打开,能不能直接回到刚才那一页?这个问题看起来微不足道,却是漫画阅读器里最容易被用户感知到的细节。进度丢一次,用户骂一次;书签不好用,用户干脆不用。断点续读听起来只是“记个页码”,真做起来要同时处理三件事:进度怎么记、书签怎么存、换设备怎么同步。我在做 Venera-Next 的过程中踩过不少坑,下面聊聊这三件事各自的取舍。
进度记在哪一层:页码还是章节
最直观的做法是记页码:第几话第几页。但漫画源的分页并不稳定,同一话在不同来源下页数可能不一样,源站更新后图片顺序也可能调整。只记页码,换个源就错位。
我最后的做法是分两层记:章节 ID 加页码,章节 ID 是主键,页码是辅助。打开一话时先按章节 ID 定位,页码只在同一章节内有效;如果章节内容变了,页码超出范围就退到章节开头,而不是硬跳到一个不存在的页。代价是进度表要多一个字段,读取时多一次判断,但换来的是换源、更新后进度基本不丢。
还有一个细节:进度什么时候写。翻一页写一次最保险,但漫画动辄上百页,频繁写数据库既耗电又容易在退出瞬间丢最后一次写操作。我改成节流写:翻页时只更新内存里的进度,每隔几秒或者退出阅读页、切后台时再落盘。退出时写一次是底线,哪怕应用被系统杀掉,丢失的也只是最后几秒的进度,而不是整段阅读记录。
书签:越多越好,还是越少越好
书签和进度是两回事。进度是自动的、唯一的;书签是手动的、可以有多个。很多阅读器把两者混在一起,结果是书签列表越攒越长,最后没人翻。
我给自己定了三条规矩。第一,书签只记用户明确标记的位置,绝不自动生成“上次看到这”。自动生成的东西和进度重复,纯属添乱。第二,书签要带一句话备注的入口,哪怕大多数人留空,有备注的书签才找得回来;没有备注的书签列表,翻到第三屏就全是“第 42 话”这种看不出区别的条目。第三,书签列表按漫画分组、按时间倒序,最新标记的在最上面——人找书签时找的永远是最近的那一个。
删除也要顺手。长按删除、左滑删除都行,关键是删完给一个可撤销的提示。误删书签的挫败感比没有书签还强,一个三秒内可撤销的 SnackBar 能省掉很多投诉。
跨设备同步:能同步什么,就同步什么
本地漫画没有服务器账号,进度同步天然受限。WebDAV 是我选的同步载体:用户自己的网盘,不用我搭服务器,也不用我存用户数据。但 WebDAV 同步进度有自己的麻烦。
首先是冲突。手机上看到第 10 话,平板上看到第 8 话,同步时以谁为准?我的做法是按最后修改时间取胜,同时保留一份本地备份。时间戳取胜简单粗暴,但对阅读进度这个场景够用:人同一时间只会在一台设备上看,时间戳新的那份几乎总是对的。真遇到两台设备同时看的极端情况,丢掉旧的那份也只是少记几页,不是灾难。
其次是同步频率。每次翻页都同步等于拿网盘当数据库,既慢又容易触发限流。我改成只在退出阅读页、切换漫画、应用退后台这三个时机同步一次。同步失败也不弹窗打断阅读,只在后台默默重试,下次打开时再补一次。阅读是连续体验,同步是后台杂事,不能让杂事打断正事。
最后是同步什么。进度、书签、阅读历史这三类数据体积小、变化频繁,适合同步;图片缓存体积大、随时可以重建,坚决不同步。把缓存也塞进同步队列,是我早期犯过的错,结果是同步一次要传几百兆,网盘直接报限流。
历史记录:记下来,更要能清掉
阅读历史是断点续读的另一面:用户想接着看,却忘了看到哪本。历史列表按最后阅读时间倒序,是最符合直觉的排序。但历史也有坑:一是隐私,有人不想让别人看到自己在看什么;二是膨胀,看过的漫画越来越多,列表越来越长。
我的取舍是:历史默认开启,但提供一键清空和按条删除,并且不把历史当成推荐依据。历史只是“接着看”的入口,不是画像。这一点在本地漫画场景下尤其重要:数据只存在用户自己的设备上,我不上传、不分析,也就没有泄露的余地。
结语
断点续读的本质,是把“人刚才在哪”这件事记准、存稳、找得到。章节 ID 加页码的两层进度、节流落盘、带备注的手动书签、时间戳取胜的轻量同步、默认开启但随时可清的历史——每一项都不是什么高深技术,难的是在“记全”和“记稳”之间选对位置。
这些取舍都沉淀在 Venera-Next 这个开源项目里,它是一个免费、无广告、GPL-3.0 的 Flutter 跨平台漫画阅读器,支持本地漫画、WebDAV 漫画源与第三方网络漫画源。如果你也在做阅读器,或者正被进度丢失、书签混乱折磨,希望这篇里的几个坑能帮你少踩一个。
- 点赞
- 收藏
- 关注作者
评论(0)