ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

legado 书源首页模块 `homepageModules` 配置完全指南:从字段规范到源码级加载机制

legado 书源首页模块 `homepageModules` 配置完全指南:从字段规范到源码级加载机制 移动开发前端应用【免费下载链接】legado-with-MD3使用 Material Design 3 全新设计的阅读 3.0项目地址https://gitcode.com/gh_mirrors/le/legado-with-MD3点击查看免费下载homepageModules是 legado阅读 3.0书源 JSON 中的一项扩展字段它允许书源作者通过一个 JSON 数组声明应用首页要展示的多个内容模块横滑轮播、排行榜、推荐卡片、网格、瀑布流、快捷按钮组等并支持用户对模块进行排序、显隐与自定义管理。本文以 docs/spec/homepage-modules.md 规范文档为骨架结合仓库内HomepageViewModel、HomepageModels.kt等源码实现完整讲解数据结构、模块类型、布局配置、数据绑定与降级逻辑并给出可直接复制使用的 JSON 示例帮助书源开发者写出高质量、可被首页正常解析与渲染的书源配置。1. 什么是homepageModules书源的首页版面声明在 legado 的书源数据结构中BookSource实体通过var homepageModules: String?字段保存一段 JSON 字符串见 app/src/main/java/io/legado/app/data/entities/BookSource.kt。当书源携带该字段时应用首页会依据它渲染出对应模块当字段为空时首页则退化为常规的发现页展示。从架构上看homepageModules是一份声明式配置它只描述首页有哪些模块、每个模块长什么样、数据从哪里来具体的解析、同步、加载与渲染由应用侧完成。解析入口位于 HomepageViewModel.kt 的parseModuleDefs其中通过GSON.fromJsonArrayModuleDef(json)把 JSON 数组映射为ModuleDef对象列表并逐个注入sourceUrlprivate fun parseModuleDefs(source: BookSource, json: String): ListModuleDef GSON.fromJsonArrayModuleDef(json).getOrDefault(emptyList()) .map { it.copy(sourceUrl source.bookSourceUrl) }ModuleDef的完整字段定义在 app/src/main/java/io/legado/app/domain/model/HomepageModels.ktdata class ModuleDef( val key: String , val type: String , val title: String , val args: String? null, val layoutConfig: String? null, val url: String? null, val sourceUrl: String , )每个模块在应用内会以ModuleItem的形式持久化数据库用于保存用户的排序、显隐、自定义标题等本地状态ModuleDef.globalIdOf(sourceUrl, key, setId)会生成形如setId::sourceUrl::key的全局唯一 ID保证同一书源下每个模块可被稳定追踪。2. 数据结构模块通用字段homepageModules是一个包含多个模块定义对象的 JSON 数组数组中每个对象支持以下通用字段字段类型必须说明keyString是模块唯一标识。建议使用[a-z0-9_]字符。用于保存用户的排序/显隐设置。typeEnum是模块类型。定义了渲染方式和交互逻辑。titleString是模块默认标题。用户可在本地自定义覆盖。kindTitleString否用于匹配源「发现」规则中的分类标题。匹配成功后自动继承其 URL 和规则。urlString否显式指定数据接口 URL。优先级高于kindTitle。支持变量替换。argsString否附加参数。在buttonGroup类型中为 JSON 数组字符串。layoutConfigObject否布局配置对象用于调整列数、行数、图标等。几点需要特别注意的语义key是模块的身份标识。源码中ModuleDef.globalId由sourceUrl key派生因此同一书源内key不可重复key的稳定性还直接决定用户排序/显隐设置能否在书源更新后保持不变。title与用户自定义的关系。ModuleItem中提供了customTitle覆盖字段其displayTitle计算逻辑为customTitle ?: title见 HomepageModels.kt。也就是说用户在端内改名后展示的是customTitle但书源 JSON 中的title始终保留为默认值。kindTitle与url二选一或都不填它们共同决定模块的数据来源优先级与降级规则详见第 5 节。3. 模块类型Module Typestype字段的值决定模块的渲染方式与交互逻辑。应用侧用枚举HomepageModuleType统一管理这些类型见 HomepageModels.ktenum class HomepageModuleType(val key: String, val title: String) { Banner(banner, 横滑轮播), Ranking(ranking, 排行榜), GridRanking(gridRanking, 网格排行榜), Grid(grid, 网格), Card(card, 推荐卡片), InfiniteGrid(infiniteGrid, 无限网格), ButtonGroup(buttonGroup, 按钮组), Waterfall(waterfall, 错位瀑布流), Unknown(, 未知); }枚举中未列出的类型会被归为Unknown对应fromKey返回Unknown端内不会正常渲染。3.1 列表与轮播类类型描述特点banner横滑轮播图适合展示高权重的精品推荐使用大图封面ranking排行榜列表垂直列表展示带排名序号card推荐卡片横向滑动的卡片流同时显示封面、标题及简介3.2 网格类类型描述特点grid标准网格最常用的展示形式支持自定义行列gridRanking网格排行榜多行多列的排行展示横向翻页infiniteGrid无限网格垂直滚动的网格流无限加载waterfall错位瀑布流垂直错位排列的书架流无限加载3.3 功能类类型描述特点buttonGroup快捷按钮组渲染为一组圆形/图标按钮支持自动填充宽度与自动分列。通常用于放置常用分类或功能入口无限流加载waterfall与infiniteGrid是两种支持无限加载的模块。源码中通过isInfinite(type, layoutConfig)判断见 HomepageViewModel.kt其判定条件是type Waterfall.key || type InfiniteGrid.key。无限模块加载第一页后会携带hasMore true用户滚动到底部时由loadMoreModule(globalId)按页码page 1继续拉取下一页并对新书按bookUrl去重后追加到列表尾部见 HomepageViewModel.kt。4. 布局配置LayoutConfig通过layoutConfig对象可以精细化控制模块的表现。规范中定义的核心属性如下属性类型适用类型默认值说明columnsIntgrid,waterfall,infiniteGrid3每行显示的列数iconStringbuttonGroup-按钮组的默认统一图标 URLiconsObjectbuttonGroup-图标映射表。例{排行: http://path/to/icon}值得补充的是应用端在解析layoutConfig时会把每个键加上layout_前缀存入配置缓存见 HomepageViewModel.kt同时将数字类型值做归一化处理整数转为不带小数的字符串。这意味着layoutConfig中未来可扩展更多键值对例如规范示例里ranking模块使用的rows每页行数、首页默认网格行数HOMEPAGE_DEFAULT_GRID_ROWS 2见 HomepageViewModel.kt均走同一套前缀 原样字符串的缓存机制供 UI 层读取。对于buttonGroupicons是一个以分类标题为键、图标 URL 为值的映射表用于为不同按钮指定不同图标未命中的按钮回退到icon指定的统一图标。5. 数据绑定逻辑Data BindinghomepageModules中每个模块的数据来源按以下优先级解析自动匹配kindTitle如果提供了kindTitle系统会遍历源exploreKinds()返回的分类列表若某个分类的title与之完全一致该模块将自动使用该分类的url即分类的发现 URL 及其规则。静态指定url如果提供了url系统将直接请求该 URL其优先级高于kindTitle。降级逻辑若kindTitle未匹配且无url模块将回退至源的主exploreUrl即该书源发现页默认的探索地址。5.1 源码中的实现印证exploreKinds()是这套绑定逻辑的数据基础实现在 app/src/main/java/io/legado/app/help/source/BookSourceExtensions.kt。它会解析书源的exploreUrl规则支持 JS 动态生成与分隔的静态分类串返回ListExploreKind每个ExploreKind包含title与url。实现中还带两级缓存内存ConcurrentHashMapACache并以bookSourceUrl exploreUrl的 MD5 作为缓存键分类规则变更后会自动重新计算无需手动刷新。在 HomepageViewModel.kt 的loadModule中可以看到三类典型绑定路径ranking/gridRanking的分组加载当模块的args是{isHomepageRankingGroup: true, kindTitles: [...]}形式的 JSON由端内从分类添加排行榜功能生成见addRankingFromKinds系统会为每个命中的分类并行发起exploreBooksUseCase.executeForRanking(sourceUrl, kind.url, null)请求最终渲染为一个带多个分类子页签的排行榜组rankingKindTitles()负责解析这种分组参数见 HomepageViewModel.kt。buttonGroup的按钮映射args是 JSON 数组字符串如[武侠, 仙侠, 都市, 历史]系统用这些标题去exploreKinds()结果中逐个精确匹配若args为空或未匹配到任何分类则退化为取前HOMEPAGE_MAX_BUTTON_GROUP_KINDS 5个分类见 HomepageViewModel.kt。普通模块的通用加载ranking/gridRanking走executeForRanking排行榜场景无分页翻页语义其余类型走exploreBooksUseCase.execute(module.sourceUrl, module.url, module.args)并返回分页结果url为空时由上层回退到源的exploreUrl见 HomepageViewModel.kt 与rawModulesFlow中val exploreUrl module.url ?: source?.exploreUrl的取值逻辑。5.2 模块同步与增量更新应用在后台会执行syncModulesFromSource(source)见 HomepageViewModel.kt把书源 JSON 中的模块定义与本地数据库对齐以JSON 全文的 MD5jsonHash作为版本标记已存在且isUserCreated false的模块若 JSON 哈希未变则跳过避免覆盖用户设置JSON 哈希变化时更新type/title/args/url等可同步字段新增模块按数组顺序写入并默认启用isEnabled true归入src_sourceUrl自动分组书源 JSON 中已删除的模块会通过deleteStale清理保证首页与书源声明一致。同时端内支持把模块重新归属到用户自建分组CustomSetItem无限流模块在移动或新增时会校验同一分组内最多一个无限模块并弹出homepage_module_duplicate_infinite提示见addCustomModule、updateModule、assignModuleToCustomSet。6. 完整 JSON 示例以下是一个包含横滑轮播、快捷按钮组、排行榜与瀑布流四种模块的完整homepageModules配置可直接嵌入书源 JSON[ { key: top_banner, type: banner, title: 精品强推, kindTitle: 首页推荐 }, { key: quick_nav, type: buttonGroup, title: 分类导航, args: [\武侠\, \仙侠\, \都市\, \历史\], layoutConfig: { icon: https://example.com/icons/default.png, icons: { 武侠: https://example.com/icons/wuxia.png } } }, { key: hot_rank, type: ranking, title: 热门榜单, kindTitle: 排行榜, layoutConfig: { rows: 5 } }, { key: explore_waterfall, type: waterfall, title: 发现更多, kindTitle: 全部, layoutConfig: { columns: 2 } } ]对照前文的字段与绑定规则逐条解读该示例top_bannerkindTitle 首页推荐自动匹配书源发现分类中标题为首页推荐的分类并继承其 URL以横滑轮播大图渲染。quick_navbuttonGroup按钮组args声明四个分类标题layoutConfig.icon是兜底图标icons为武侠指定专属图标其余按钮使用默认图标。hot_rankkindTitle 排行榜匹配排行榜分类layoutConfig.rows 5控制每页展示行数垂直列表带序号渲染。explore_waterfallkindTitle 全部若匹配不到则回退到书源主exploreUrlcolumns 2指定两列错位瀑布流支持无限加载。7. 编写建议与注意事项综合规范文档与源码实现书源作者编写homepageModules时应注意key一经发布尽量保持稳定。它是模块在应用内持久化的唯一标识sourceUrl key组成全局 ID也承载用户排序与显隐设置随意改动key会导致旧模块被当作新模块重新创建用户设置丢失。kindTitle必须与发现分类title完全一致区分大小写的精确匹配否则会落入降级分支。匹配不到时有url用url都没有则回退到书源主exploreUrl。buttonGroup的args是 JSON 数组字符串不是普通字符串字段名与 JSON 编码都要正确例如args: [\武侠\, \仙侠\]。未提供args或全部匹配失败时端内自动取前 5 个分类兜底。waterfall/infiniteGrid是无限流模块同一分组内建议只放一个应用会主动拦截重复的无限流模块添加。layoutConfig采用键值对 layout_前缀的通用解析机制除了规范中的columns、icon、icons还可以按 UI 需要扩展如rows等自定义键数值会被归一化为字符串传递。明确url与kindTitle的取舍url优先级最高、最直接适合数据接口独立于发现分类的场景kindTitle复用发现规则维护成本低但依赖分类标题的稳定性。8. 小结homepageModules让 legado 的首页从一个固定的发现列表升级为由书源自行声明的可组合版面通过type选择呈现形态轮播、榜单、卡片、网格、瀑布流、按钮组通过kindTitle/url声明数据来源通过layoutConfig微调布局细节。配合应用端的模块同步MD5 增量对齐、用户自定义分组、排序显隐与无限加载机制一份精心编写的homepageModules可以让书源在首页获得极高的信息密度与可读性。书源作者可直接以本文第 6 节的 JSON 为模板对照第 24 节字段表逐项配置希望深入理解加载链路的开发者可继续阅读 HomepageViewModel.kt、HomepageModels.kt 与 BookSourceExtensions.kt 三处核心源码以及 首页模块规范文档 获取最新约定。赞分享移动开发前端应用【免费下载链接】legado-with-MD3使用 Material Design 3 全新设计的阅读 3.0项目地址https://gitcode.com/gh_mirrors/le/legado-with-MD3点击查看免费下载相关推荐OfficeCLI 上手3 条命令跑通 Word、Excel、PPT 的 Office 自动化OfficeCLI 上手3 条命令跑通 Word、Excel、PPT 的 Office 自动化 凌晨一点AI 助手被要求把季度数据整理进 Excel顺手把移动开发前端应用UnoCSS 配置文件完全指南从 uno.config.ts 编写到源码级加载机制UnoCSS 配置文件完全指南从 uno.config.ts 编写到源码级加载机制 UnoCSS 是一个即时按需生成的原子化 CSS 引擎而 配置文件 是驾前端构建工具Blockly 滑块字段插件 blockly/field-slider 完全指南从安装配置到源码级原理Blockly 滑块字段插件 blockly/field slider 完全指南从安装配置到源码级原理 blockly/field slider 是 Bl前端低代码UI组件上一篇RPCS3模拟器终极配置指南让旧电脑也能流畅运行PS3游戏的5个秘诀下一篇Learn Harness Engineering 德语参考库完全指南从模板文件到可运行 Harness 的落地方法创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表