项目深挖:Android PDA 仓储系统的业务与技术落地
从被动元器件仓库的真实风险出发,梳理 Kotlin、Jetpack Compose、扫码输入、收货上架、拆分上架、拣货复核与客户配置。
这篇文档只保留当前项目中能讲清楚的 RN 与 Android 相关内容。仓储系统的重点不是界面炫技,而是让现场人员在高频操作下少出错、能追溯、遇到异常知道怎么处理。
一句话定位
这是面向被动元器件仓库的 Android PDA 系统,覆盖入库收货、上架、拆分上架、出库拣料、拣货和出库复核等流程。项目基于客户实际仓储逻辑进行适配,目标是减少人工录入和错贴、错拣、错发造成的损失。
面试时可以先说:
随着被动元器件客户的仓库规模扩大,型号、批次和数量相近,贴错标签、拣错货或发错货的成本会很高。我们开发 PDA,把收货、上架、拣货和复核过程中的关键判断放到系统里,通过扫码和订单明细减少人工操作错误。
为什么选择原生 Android
我使用 Kotlin 和 Jetpack Compose 从 0 到 1 开发 PDA 客户端。选择原生方案不是因为 RN 不能做 PDA,而是这个场景更需要直接控制:
- PDA 扫码枪的输入事件和键盘模拟行为。
- CameraX 与 ML Kit 的摄像头扫码。
- 不同硬件设备的焦点、生命周期和系统行为。
- 仓库现场连续扫码时的响应速度和稳定性。
界面可以简洁,但不能粗糙。操作员需要大按钮、清晰状态、少步骤和明显的成功/失败反馈。
核心业务链路
销售订单到出货申请
销售人员先创建销售订单,填写型号、数量和价格,审核通过后转成出货申请。拣货人员依据出货申请执行作业,而不是直接按照口头信息取货。
收货
收货重点确认“收到的货是否正确”:
- 物料型号。
- 收货数量。
- 批次或 DC 等标识。
- 箱体或物料二维码。
收货完成后,系统形成库存明细和库存 ID。后续上架操作基于这条库存记录进行,不能由客户端随意创建库存。
上架与拆分上架
上架解决的是“库存放到哪个库位”。如果同一批库存需要放到多个库位,就进入拆分上架流程:确认原箱库存和可用数量,指定目标库位,扣减原库存并创建目标库存记录。原库存还有剩余时,保留剩余库存。
拆分上架是库存变化操作,需要由后端事务保证原库存扣减和新库存创建的一致性。客户端负责传递准确的库存快照、请求 ID和用户输入,并在失败后保留页面状态、提示原因和重新加载数据。
扫码输入的两条入口
当前 PDA 主要有两种扫码入口,最终都归一为一个字符串结果:
PDA 扫码枪
设备通常使用键盘模拟模式,把扫码内容输入到 EditText,完成后发送回车。客户端监听回车,读取输入内容并清空输入框,再交给业务层处理。
面试时不要把键盘模拟说成广播接收。只有真正实现了 BroadcastReceiver 注册和 onReceive 才能称为广播模式。
摄像头扫码
摄像头侧使用 CameraX 提供图像帧,ML Kit 识别二维码。一个扫码窗口只接受第一条有效结果,后续连续帧不重复回调;关闭页面时释放分析器、相机和扫码器。
两种入口都不应该各自实现收货、拣货和复核逻辑,而是统一交给业务层做格式校验、状态校验和接口提交。
标签规则为什么难
不同客户的标签规则不完全一致:
- 有些客户使用公共标签,同一个箱内多个盒子的二维码相同。
- 有些客户使用唯一标签,每个盒子都有唯一序列号。
公共标签只能证明物料或箱体身份,不能独立区分每一盒。因此公共标签场景需要手动输入或确认数量,并允许在当前任务中删除错误记录;唯一标签则可以通过二维码和序列号做逐个追踪及重复校验。
面试表达:
我把标签处理分成公共标签和唯一标签两类。公共标签依赖当前订单、箱体和累计数量校验;唯一标签额外记录序列号,用于逐个追踪和防止重复使用。二维码无法识别时,人工录入只是异常兜底,最终仍然绑定已有库存明细,并经过后续复核。
拣货与复核为什么分开
拣货负责按出货申请取货,复核负责在出库前独立确认结果。复核人员以订单明细和系统记录为依据,再次校验:
- 物料型号是否一致。
- 累计数量是否正确。
- 唯一标签是否属于当前订单、是否重复。
- 公共标签的数量是否符合订单要求。
发现多拣、少拣、错料或标签不匹配时,系统应该阻止复核通过,生成异常并退回处理,而不是让操作员直接绕过校验。
一致性与重复提交
requestId
一次库存变更生成一个业务请求 ID。网络超时重试时复用原 ID,后端据此识别同一次操作,避免重复扣库存或重复入库。当前代码中,收货、出库拣货和拆分上架都能看到这种请求 ID 的使用方式。
stockVersion
库存版本主要用于拆分上架流程:扫描原箱时获取库存版本,提交时带回 sourceStockVersion。如果页面停留期间库存已被其他操作修改,后端发现版本不一致,就拒绝基于旧快照继续操作。
面试时要限定范围:
我在拆分上架流程中接入了库存版本校验和请求幂等,不把它泛化成所有 PDA 流程都已经具备同样的并发控制。
OTA 更新
PDA 采用全量 APK 更新。服务端通过 manifest 描述版本号、下载地址和校验信息,客户端比较版本后下载 APK。下载先写入临时文件,完成并校验通过后才弹出系统安装;下载不完整或校验失败时保留当前版本。
全量 APK 适合同时更新业务代码、原生代码、Compose 页面、扫码依赖和设备适配能力,避免业务代码和原生能力版本不一致。当前更新采用用户主动选择,不在用户执行拣货或收货时强制打断。
客户定制如何产品化
核心仓储链路尽量保持统一,不因为单个客户复制一套页面。客户差异优先通过以下方式承载:
- 菜单和权限配置。
- 字段、提示和展示方式配置。
- 公共组件的少量适配。
- 标签规则和扫码模式的适配层。
只有具有行业复用价值的差异,才进入公共能力。客户提出超出标准流程的需求时,先记录场景、目标和影响范围,提交产品或项目负责人评估,不在现场直接承诺改核心流程。
面试中的职责边界
推荐说法:
我负责 PDA 客户端的 Kotlin + Compose 页面、扫码输入、接口联调、核心仓储流程接入和版本更新。部分代码实现使用了 AI 辅助,但我负责把客户流程拆成客户端状态、接口请求和异常反馈,完成真机验证和现场问题修复。
如果不确定某个底层细节,不要硬编:
这部分实现我需要回看源码确认,但从业务上它解决的是重复扫码/重复提交问题;我当时负责的是接口接入、流程验证和异常处理。
高频追问速答
为什么不能全部离线拣货?
拣货、出库和调拨会改变库存状态。网络断开时无法确认库存版本和上一笔操作结果,继续离线提交容易造成库存账实不一致,因此这类关键写操作优先禁止继续提交;恢复网络后再核对和处理。
公共标签怎么防止多拣?
公共标签通过手动数量和累计数量校验控制,拣货后再由复核人员按订单明细核对。数量不一致时阻止出库,不能只依赖二维码本身。
AI 在项目里做了什么?
AI 帮助生成重复代码、分析报错和提高实现效率;业务流程、接口字段、设备验证和最终上线质量由我确认和负责。
最后怎么收尾
这个项目的价值不是做了一个扫码页面,而是把不同客户的仓库规则和高风险操作,沉淀成可执行、可复核、可追踪的 PDA 流程,帮助客户减少人工录入和错发风险。