Android/Retrofit:后端无401时如何每15/30分钟手动刷新令牌?
手动定时刷新双令牌的最佳实现方案
针对你遇到的API不返回过期错误、需按固定时间刷新双令牌的场景,以下是几个实操性强的方案,按适配性排序:
1. 会话绑定的固定定时器(最贴合后端要求)
直接在用户登录成功、拿到初始令牌后,启动两个独立的定时任务:
- 第一个定时器每15分钟触发一次第一个令牌的刷新请求
- 第二个定时器每30分钟触发一次第二个令牌的刷新请求
实现要点:
- 用对应平台的原生定时器API:
- 后端/服务端:用
ScheduledExecutorService(Java)或setInterval(Node.js),注意线程安全 - 前端:用
setInterval,但要监听页面可见性,页面休眠时可暂停定时器减少无效请求 - 移动端:Android用
Handler+postDelayed(前台)或WorkManager(后台保活);iOS用Timer(前台)或BackgroundTasks(后台)
- 后端/服务端:用
- 每次刷新成功后,立即更新本地存储的令牌;刷新失败时,先重试1-2次(间隔几秒),仍失败则弹窗提示用户重新登录
- 用户登出或会话失效时,必须主动取消所有定时器,避免发起无效请求
优缺点:
- ✅ 完全匹配后端要求的时间节点,逻辑简单直接,无需依赖API错误码
- ❌ 用户长时间无操作时仍会产生刷新请求,浪费流量;定时器可能因进程/页面销毁失效(需额外做保活处理)
2. 定时器+请求拦截预刷新(优化版)
在固定定时器的基础上,加入请求前的令牌有效期检查,减少不必要的定时请求:
- 每次发起API请求前,先检查令牌的剩余有效期(需后端返回令牌时附带过期时间,或前端用「令牌获取时间+有效期」计算)
- 如果第一个令牌剩余时间不足2分钟(可自定义阈值),先触发刷新再发起请求;同理处理第二个令牌
- 保留原15/30分钟的定时器作为兜底,避免用户长时间无请求导致令牌过期
实现要点:
- 在Interceptor中添加有效期校验逻辑,同时要做并发控制:比如用原子标记位,同一令牌同一时间只允许发起一次刷新请求,避免重复刷新
- 刷新请求要同步更新所有等待中的API请求的令牌,确保后续请求用新令牌
优缺点:
- ✅ 减少无效刷新请求,同时保证令牌不会在请求时过期
- ❌ 需要额外维护令牌有效期信息,实现复杂度略高
3. 系统级后台任务(移动端专属)
如果是Android/iOS应用,用系统提供的后台任务组件实现稳定的周期性刷新:
- Android:用
WorkManager创建PeriodicWorkRequest,分别设置15分钟和30分钟的重复间隔,即使应用在后台也能执行 - iOS:注册
BGAppRefreshTask或BGProcessingTask,注意需符合苹果的后台执行规则(不能过于频繁,否则会被系统限制)
实现要点:
- 任务执行前先检查用户是否处于登录状态,避免无效操作
- 刷新成功后更新本地安全存储的令牌;失败则记录日志,等待下一次任务重试
优缺点:
- ✅ 不受应用进程状态影响,稳定性更高
- ❌ 移动端系统对后台任务有严格限制,无法保证100%准时执行
通用注意事项
- 刷新请求必须设计为幂等,多次调用不会导致令牌状态异常
- 处理刷新失败的边界场景:网络错误时用指数退避重试(比如第一次等3秒,第二次等6秒),重试3次后仍失败则触发登录流程
- 令牌存储要安全:后端用Redis等带过期的存储;前端用加密后的
localStorage;移动端用系统安全存储(Android EncryptedSharedPreferences、iOS Keychain)
内容的提问来源于stack exchange,提问作者Regress.arg
相关产品推荐
相关产品推荐

