Android 学习笔记 D21一次收藏错位和返回异常怎样定位真正的根因发布摘要用一个可重复制造的跨页面问题完成第三周回归追踪收藏事实来源、首页身份和网页返回事件。标签Android、调试、状态管理、项目复盘。前六天增加了主题、滑页、传统列表、网页阅读、分享和后台任务。每个功能单独演示都正常连起来却可能出错。本篇构造一个教学诊断案例从收藏页进入详情取消收藏再打开网页并分享最后返回旧收藏仍出现页签还跳回文章。这个案例是用于复现与推理的实验不是已经发生在用户项目里的真实经历。本文对应 D21。相关基础回读《第一行代码》第 3—5 章的页面与列表、第 7—8 章的存储与组件、第 10—11 章的服务与网络以及第 13.6 节后台任务。今天不增加新库目标是把多个局部正确的功能组成一个一致的系统。一、先写操作路径暂时不要修改代码准备三十篇带不同编号的受控文章至少收藏二十篇使收藏列表超过一屏。进入收藏页并滚到一个不在首屏的固定编号记录它为本次目标打开详情、取消收藏然后打开原文 A、从 A 跳到 B、打开分享面板并取消。连续返回直到再次看到首页。预期分成三件事先由 B 回 A再退出阅读页详情中收藏已取消回到原首页时仍位于收藏页目标编号已经消失。只有把三个预期分开才不会把“回来看到第一页”与“收藏数据错误”误认为同一个导航问题。复现后先记录实际现象再提出假设。如果只看到收藏图标错了不应直接断言数据库未写入如果日志出现多个首页对象也不等于一定存在泄漏可能是错误导航创建了新的条目。二、沿着事件和数据分别追踪事件方向是按钮到 ViewModel再到 Repository 和 DAO数据显示方向是数据库流到 ViewModel再到各页面。诊断要在边界处记录同一个文章编号不要只写“点击成功”“刷新完成”这样无法关联的日志。以下是放在调试源码中的完整辅助对象需要android.util.Log和java.util.concurrent.atomic.AtomicLong。它只记录可公开的文章编号、状态摘要和实例标签不记录令牌、文件内容或完整网页参数。尚未在用户工程编译运行。importandroid.util.Logimportjava.util.concurrent.atomic.AtomicLongobjectFlowTrace{privatevalsequenceAtomicLong()funrecord(stage:String,articleId:Long?,detail:String){valordersequence.incrementAndGet()Log.d(ArticleTrace,#$orderstage$stageid$articleId$detail)}funinstanceTag(value:Any):StringInteger.toHexString(System.identityHashCode(value))}第一处在取消按钮记录编号和目标值第二处在数据库写入完成后记录成功第三处在收藏流发射时记录编号集合第四处在页面收到状态时记录首页条目标识、页码和集合。实例标记只是调试线索不当作永久业务编号。如果写入成功且数据库流已移除编号但收藏页仍显示它范围就收缩到状态转换或 UI。检查是否写过remember { initialBookmarks }把首次输入冻结成局部副本是否有普通可变集合原地更新而没有可观察通知是否错误复用了列表 key。三、把两种故障分开修复本实验故意让收藏页缓存首次列表。修复是由共享 Repository 的最新流生成 UI 状态让页面直接消费并用文章编号作为稳定 key。不要用“返回后手动刷新一次”掩盖副本因为下一次详情、传统 View 页或后台任务修改数据仍可能失步。单一事实来源与数据层第二个故障故意在阅读页退出时重新创建 Home 返回项。修复是弹出当前阅读项让已有首页条目继续承担页码和列表状态而不是新建一个默认页码为零的首页。需要检查导航条目保存状态的配置只有同一个业务目的地名称并不证明是同一个返回项。Navigation 3 状态保存网页返回另设检查只有当前可见阅读页且 canGoBack 为真时网页处理器才接管系统返回。返回条件变化必须更新到可观察状态否则 UI 中的旧布尔值可能让处理器一直启用。工具栏返回与系统返回采用相同的优先级减少路径差异。四、回归应覆盖修复周边而不是只重走一次先在文章页收藏再从传统 View 页取消预期两种界面都反映数据库变化。随后从收藏页进入详情直接返回预期页码和滚动位置保持再走一次网页 A 到 B 到返回的路径预期两条栈按顺序变化。主题回归在固定深色下执行整条路径并旋转一次。若旧 View 页没有使用项目主题配置应将其列为明确差异或补齐适配不能只凭 Compose 首页截图宣称全应用一致。分享取消后不应修改收藏分享面板出现也不应被记录成发送成功。Worker 回归关注另一类问题排队时离开页面、网络恢复后写数据库重新进入应用时观察最新缓存。KEEP 避免同名未完成工作堆积但页面刷新仍可能并发因此还要检查同一文章重复写入和收藏保护。WorkManager 的唯一工作范围可以对照官方管理说明。最后重复进入退出传统页核对旧 View 的收集停止、binding 清理和 ComposeView 释放这里只证明检查过的引用链不以一次没有崩溃作为完全不存在内存问题的结论。五、怎样写成有证据的复盘段落复盘可以按这样组织“在收藏页取消后返回仍显示旧条目。数据库查询和 Flow 发射均已移除该编号但页面日志仍打印初始集合。定位到页面把首次参数保存在 remember 中。移除副本后由共享流驱动并回归详情、传统页和后台更新三种修改入口。”这段话只有完成真实实验后才能改成自己的实测经历。写博客时将证据编号、截图位置和实际版本补上如果只完成一半应如实写“已定位到 UI 副本尚未验证后台更新路径”。技术复盘的价值来自证据把原因缩小而不是使用很多排查术语。六、原创面试问答与追问可连接题库Fragment 之间通信与Activity 生命周期。以下自拟题用来检查能否解释案例。问数据写入成功界面为什么仍旧答写入到显示之间还有流转换、状态持有和观察链任何一处副本都可能滞后。追问第一步怎么查先对比数据库实际值、流发射值与界面接收值。问返回到 Home 为什么会回第一页答可能创建了新的首页条目也可能保存状态未接入。追问如何区分同时记录返回栈身份和 Pager 状态创建时机。问修复后只重测原路径够吗答还需验证共享边界上的其他入口。追问本案例选哪些详情取消、传统页取消和后台数据更新因为它们都可能暴露副本问题。七、当天练习与验收先用二十分钟预测案例现象四十分钟整理日志点一百五十分钟复现并修复三十分钟回归最后一小时闭卷讲述根因。独立任务从“网页打不开、快速切页、重新进入传统页”抽一个条件先写假设再操作。交付应是一份完整问题记录操作、预期、实际、证据、修改和回归结果。通过标准是能说明排除了哪些原因、为何修改在正确层次以及哪些扩展仍没有验证。
阅读完成 · 觉得有帮助?