news 2026/10/2 20:47:00

剖析阅读Sigma源码架构:RuleAnalyzer规则解析流水线与 Room 数据库设计

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
剖析阅读Sigma源码架构:RuleAnalyzer规则解析流水线与 Room 数据库设计

剖析阅读Sigma源码架构:RuleAnalyzer规则解析流水线与 Room 数据库设计

【免费下载链接】legado-E阅读Sigma是legado的继承,保持开源免费,延续开源精神。项目地址: https://gitcode.com/gh_mirrors/legado2/legado-E

阅读Sigma(legado-E)是一款开源免费的 Android 阅读 App,其核心竞争力在于书源规则解析——用规则把网页和接口变成可读的正文。本文以RuleAnalyzer 规则解析流水线与Room 数据库设计为主线,带你快速看懂这款开源阅读应用的源码架构,新手也能轻松上手 📚。

一、源码结构总览:每个模块管什么

项目主代码位于 app/src/main/java/io/legado/app/ 目录,与本文相关的模块可分成三块:

模块路径职责
规则解析model/analyzeRule/拆分、解析并执行书源规则
数据存储data/Room 数据库、DAO 与实体定义
业务模型model/阅读、下载、搜索等动作的编排

项目自带了两份模块说明文档:data/README.md 和 model/README.md,是阅读源码的绝佳入口。

二、规则解析流水线:书源生效的魔法

2.1 RuleAnalyzer:先把规则"切"开

一条书源规则常常长这样:

class.name;@css:div.title;@text

@前面是 XPath,后面是 JSoup 的 css 选择器。麻烦在于:规则字符串本身就可能含有@、&&、||(比如正则或 jsonPath 里就有),简单按符号切分必然出错。

RuleAnalyzer.kt 就是来解决这个问题的,它的设计思路很巧妙:

  • 不用正则、不复制中间串:只在原字符串上标记起点和终点(pos指针),最后一次性切片,源码注释原话是"高效快速准确切割规则";
  • 识别"平衡组":遇到[...]或(...)筛选器时成对匹配括号整体取出(见 RuleAnalyzer.kt 中chompBalanced的调用),筛选器内部的符号不会骗过它;
  • 区分引号与转义:单引号、双引号、转义字符分别跟踪状态(见 RuleAnalyzer.kt 的chompCodeBalanced),JS 代码块里的&&不会被当成分隔符;
  • tailrec 尾递归:splitRule方法使用 Kotlin 的tailrec注解(RuleAnalyzer.kt),避免深递归的性能损耗。

2.2 AnalyzeRule 调度器:按类型分派解析器

规则切分完成后,由 AnalyzeRule.kt 作为"总调度"接手,它内置了四个解析器:

解析器文件用途
XPathAnalyzeByXPath.ktHTML 结构解析的默认语言
JSoupAnalyzeByJSoup.ktcss 选择器语法
JsonPathAnalyzeByJSonPath.kt解析 JSON 接口响应
正则AnalyzeByRegex.kt按模式抽取内容

规则里的@分隔符让四个解析器可以任意串联使用。同时 AnalyzeRule 内置了三份缓存:stringRuleCache、regexCache、scriptCache(AnalyzeRule.kt)——同一条规则字符串、正则、JS 脚本只编译一次,后续直接复用,这对翻页、批量加载章节时的解析开销优化非常明显。

2.3 JS 脚本与变量传递

书源规则还支持 JS 脚本,引擎来自内置的 modules/rhino/ 模块(Rhino 引擎)。RuleData.kt 负责用variableMap管理跨页面传递的大变量:第一页脚本写入的 token,下一页规则可以取回——这正是"翻页加载""登录态保持"等复杂书源能跑通的底层机制。

三、Room 数据库设计:管理 21 张表的账本

3.1 单一入口:appDb 全局单例

所有数据库操作都经过一个懒加载的全局单例(AppDatabase.kt):

val appDb by lazy { Room.databaseBuilder(appCtx, AppDatabase::class.java, AppDatabase.DATABASE_NAME) .fallbackToDestructiveMigrationFrom(false, 1, 2, 3, 4, 5, 6, 7, 8, 9) .addMigrations(*DatabaseMigrations.migrations) ... }

短短几行讲了三件事:数据库首次使用时才构建(by lazy);1~9 的远古版本直接采用"重建"策略;第 10 版起才开始正规的增量迁移。

3.2 89 个版本与 AutoMigration 自动迁移

AppDatabase.kt 的@Database注解中可以看到version = 89,以及 Book、BookChapter、BookSource、Bookmark、RssSource、ReadRecord 等 21 张表定义和一个BookSourcePart视图。

项目大量使用 Room 的AutoMigration 自动迁移:普通改动(加列、加表)由 Room 自动生成迁移 SQL;只有需要手工回填数据的版本(如 54→55、80→81、84→85)才在 DatabaseMigrations.kt 中编写对应 spec 类,把成本压到最低。

另一个亮点是exportSchema = true:每个版本的数据库结构会被自动导出到 app/schemas/io.legado.app.data.AppDatabase/,共 89 个 json 文件。对贡献者来说,数据库结构的每一次变化都能在版本控制中"看见",这是多版本协作项目非常友好的实践。

3.3 DAO 与 Entity:清晰的职责分工

按照 Room 官方推荐的惯例,data/ 目录分两层:

  • entities/:21 个纯数据类(表结构),如 Book 书籍表、BookChapter 章节表;
  • dao/:21 个数据库读写入口,如 BookDao.kt、BookChapterDao.kt、BookSourceDao.kt,UI 与业务层只与 DAO 打交道,不直接接触表。

这种"实体定结构、DAO 开门面"的划分,正是数据库能稳定迭代到第 89 版而业务代码几乎不用改的原因。

四、两者如何协作:从书源到书架的数据流 💾

把解析流水线和数据库串起来,一次典型的"搜索 → 加书架 → 阅读"流程是:

  1. 用户输入关键词,App 依次执行各书源的搜索规则:RuleAnalyzer 切分 → AnalyzeRule 分派解析器;
  2. 结果写入SearchBook表(SearchBookDao.kt)供界面展示;
  3. 加入书架时,从BookSource表提取规则数据,书籍信息写入Book表;
  4. 打开书籍后按BookChapter表逐章取内容,阅读进度实时写入ReadRecord表。

一句话总结:解析流水线负责"取数",Room 数据库负责"存数",两者互不越界,层次干净利落。

五、新手源码阅读路线:30 分钟上手

如果想自己动手读源码,推荐这个顺序:

  1. 先看 data/README.md 与 model/README.md 建立模块概念;
  2. 再看 AppDatabase.kt,仅凭@Database注解就能列出这款 App 有哪 21 张表;
  3. 然后精读 RuleAnalyzer.kt,注释详尽,splitRule是核心方法;
  4. 最后看 AnalyzeRule.kt,理解四个解析器与 JS 脚本如何组合。

想本地运行项目,可以克隆源码:

git clone https://gitcode.com/gh_mirrors/legado2/legado-E

阅读Sigma 的架构并不复杂,它的功力藏在"持续迭代中保持分层清晰"上:RuleAnalyzer 的规则切分、AnalyzeRule 的总调度、Room 的 89 版自动迁移——这三件小事做到位,才撑起了它赖以生存的书源生态。

【免费下载链接】legado-E阅读Sigma是legado的继承,保持开源免费,延续开源精神。项目地址: https://gitcode.com/gh_mirrors/legado2/legado-E

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 20:43:10

电梯调度系统设计:循环链表与结构体数组的工程实践

简介:本资源是一份面向计算机专业本科生的数据结构课程设计报告,聚焦电梯模拟系统开发,旨在通过真实项目实践深化对栈、队列、链表等核心数据结构的理解与应用能力。报告完整覆盖系统分析、概要设计、详细实现、运行测试及总结反思全过程&…

作者头像 李华