5.2 KiB
5.2 KiB
业务 BaseUrl 切换 — 设计文档
- 日期:2026-09-01
- 状态:已确认
- 关联模块:网络层 / 设备初始化 / 全局配置
1. 背景与目标
SmartTakePlate(发盘机)当前业务服务地址由 GlobalData.appBaseUrl 决定,但该字段:
- 默认值为空串,全局无任何活跃代码赋值(仅剩注释)。
- 已具备一套"半成品"基础设施(
SpTool.getBaseUrl/setBaseUrl、GlobalKey.KEY_BASE_URL、LOCAL/TEST/PROD_BASE_URL常量),但从未接线。
目标:让现场运维人员能在设备端切换业务环境(本地 / 测试 / 生产),切换结果持久化, 重启后生效。
2. 需求
- 入口:设备端隐藏入口,置于登录前的初始化界面(
DeviceInitActivity)。 原因:若入口放在业务主界面,一旦配置的服务地址访问不到,业务界面因依赖网络请求成功才能 进入,将无法切回正确地址,形成死锁。 - 生效方式:持久化到 SharedPreferences,重启 app 后生效(最简单可靠)。
- 选项来源:仅预设环境列表(本地 / 测试 / 生产),不支持手输。
3. 现状分析
| 已存在 | 状态 |
|---|---|
GlobalData.appBaseUrl(var String = "") |
默认空串,无活跃赋值 |
LOCAL_BASE_URL / TEST_BASE_URL / PROD_BASE_URL |
已定义,不带尾斜杠 |
GlobalKey.KEY_BASE_URL = "baseUrlKey" |
已定义 |
SpTool.getBaseUrl() / setBaseUrl() |
已实现,无调用方 |
ApiClient.retrofit(by lazy,baseUrl(GlobalData.appBaseUrl)) |
用空串构建,切环境不重建 |
ApiService / ApiServiceV2 全部方法 |
用 @Url url = "${GlobalData.appBaseUrl}/..." 默认参数,调用时求值 |
关键结论:
- 所有请求地址由
GlobalData.appBaseUrl在每次调用时经默认参数拼接决定,故切环境 只需改这一个变量(配合重启重建Retrofit)。 GlobalData.appBaseUrl=""会让Retrofit.Builder().baseUrl("")抛异常 —— 现有隐患。
4. 设计
4.1 组件划分与改动清单
| 文件 | 改动 |
|---|---|
GlobalData.kt |
补充环境列表模型(名称 + URL),复用已有 LOCAL/TEST/PROD_BASE_URL |
MyApp.kt |
initGlobalData() 接线:读 SpTool.getBaseUrl(),兜底 TEST_BASE_URL |
DeviceInitActivity.kt |
加隐藏连点手势 + 弹环境选择弹窗 |
ApiClient.kt |
修复 Retrofit baseUrl 校验(补尾斜杠 / 占位),消除空串崩溃 |
新增 EnvironmentSelectDialog(或内联 Dialog) |
环境单选弹窗,高亮当前项 |
BaseActivity.kt(复用) |
复用已有 clearAllFace() 清人脸库 |
4.2 关键设计决策
决策 A — URL 规范化(消除现有隐患)
- 约定
GlobalData.appBaseUrl不带尾斜杠,供@Url拼接得到形如https://dev.yixiong-tech.com:8081/terminal/...的完整地址。 Retrofit的 baseUrl 单独规范化:空则占位http://localhost/,非空且无尾斜杠则补/。 因所有请求走@Url全路径,Retrofit baseUrl 不参与实际拼接,只需合法即可。
决策 B — 切换时清理环境残留
选中环境后执行:
SpTool.setBaseUrl(url)持久化;- 清空本地人脸库(
FaceDatabase/clearAllFace()); - 重置人脸时间戳
lastFaceTimestamp = 0; - 重置
firstGetFace = true。
原因:不同环境的人脸数据与时间戳不同,不清理会导致重启后增量同步对不上。
另:ArcSoft 激活参数(appId / sdkKey / activeKey)无需单独处理——DeviceInitActivity
每次启动都会调用 getDeviceConfig() 从新环境重新获取并覆盖,切环境后自动适配。
决策 C — 隐藏手势
在 DeviceInitActivity 连续点击屏幕(如 5 次)触发,不新增可见 UI 元素。该界面登录前
可达、不依赖网络,满足"配错地址也能切回"的要求。
5. 数据流
sequenceDiagram
participant User as 运维人员
participant App as MyApp/DeviceInit
participant Sp as SpTool(SharedPrefs)
participant Net as Retrofit/网络
App->>Sp: 启动时读 KEY_BASE_URL
alt 有值
Sp-->>App: 返回已存 URL
else 无值(首次)
Sp-->>App: 空 → 用 TEST_BASE_URL
end
App->>App: GlobalData.appBaseUrl = 结果
User->>App: 初始化界面连点5次
App->>App: 弹环境选择Dialog(高亮当前)
User->>App: 选择「生产」并确认
App->>Sp: setBaseUrl(PROD)
App->>App: 清人脸库 + 重置时间戳 + firstGetFace=true
App->>User: Toast「重启后生效」
User->>App: 重启 app
App->>Net: appBaseUrl 已指向生产 → 全量拉新环境人脸
6. 错误处理
- baseUrl 空 / 非法:兜底
TEST_BASE_URL,并保证 Retrofit baseUrl 合法(占位/补斜杠)。 - 清人脸库失败:非致命,仅记日志,不阻塞切换(重启后首次拉取仍会兜底全量)。
- 写 SharedPreferences 失败:几乎不抛;Toast 提示用户重试。
7. 验证方式
- 构建:
./gradlew assembleDebug通过。 - 手动:初始化界面连点 5 次 → 弹窗 → 切「本地」→ 重启 → 抓包/日志确认请求打到新地址; 再切回「测试」验证可恢复。