Kotlin实现5分钟无操作自动登出功能问题求助
自动登出功能的问题分析与修复
你的代码核心问题
Logout Activity的设计逻辑完全错误
这个Activity在onCreate里直接启动了LoginActivity,导致它刚创建就被系统销毁,后续的检查任务(checkRunnable)根本没有机会持续运行,自然不会触发登出。自动登出逻辑不应该放在一个独立的、瞬间就被跳转的Activity中。其他代码问题
- 在IO协程里启动Activity:
GlobalScope.launch(Dispatchers.IO)中调用startActivity是错误的,必须在主线程执行UI相关操作。 lastInteractionTime初始值为0:第一次检查时,若用户还没操作,会直接判定超时,应该初始化为当前时间。GlobalScope滥用:全局协程没有绑定生命周期,可能导致内存泄漏。- 仅监听单个Activity的触摸事件:用户在其他Activity的操作不会重置计时器,无法实现全局无操作检测。
- 在IO协程里启动Activity:
正确实现方案:全局监听用户交互
推荐通过BaseActivity基类实现,让所有业务页面继承这个基类,统一处理无操作计时:
步骤1:创建BaseActivity基类
abstract class BaseActivity : AppCompatActivity() { @Inject lateinit var personsService: PersonsService private var lastInteractionTime: Long = System.currentTimeMillis() private val INACTIVITY_TIMEOUT = 5 * 60 * 1000 // 5分钟 private val CHECK_INTERVAL = 60 * 1000 // 1分钟检查一次 private val handler = Handler(Looper.getMainLooper()) private val checkRunnable = object : Runnable { override fun run() { val currentTime = System.currentTimeMillis() if (currentTime - lastInteractionTime >= INACTIVITY_TIMEOUT) { // 执行登出逻辑 performLogout() } // 继续循环检查 handler.postDelayed(this, CHECK_INTERVAL.toLong()) } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 启动检查任务 handler.postDelayed(checkRunnable, CHECK_INTERVAL.toLong()) } // 重置计时器:监听所有用户交互事件 override fun dispatchTouchEvent(event: MotionEvent): Boolean { lastInteractionTime = System.currentTimeMillis() return super.dispatchTouchEvent(event) } override fun onStop() { super.onStop() // 页面停止时移除回调,避免内存泄漏 handler.removeCallbacks(checkRunnable) } override fun onResume() { super.onResume() // 页面恢复时重新启动检查任务 handler.postDelayed(checkRunnable, CHECK_INTERVAL.toLong()) // 恢复页面时重置计时器 lastInteractionTime = System.currentTimeMillis() } private fun performLogout() { // 在主线程执行UI操作,登出接口调用放在IO线程 lifecycleScope.launch { val request = CerrarSessionRequest(false) withContext(Dispatchers.IO) { personsService.logoutVM(request) } // 启动登录页,清除所有栈内页面 val intent = Intent(this@BaseActivity, LoginActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK } startActivity(intent) finish() } } }
步骤2:业务Activity继承BaseActivity
比如你的首页、个人中心等页面,都修改为:
class MainActivity : BaseActivity() { // 你的页面逻辑 }
额外优化点
- 如果需要监听应用后台状态(比如切后台5分钟也登出),可以在Application里注册
ActivityLifecycleCallbacks,监听应用前后台切换,在切后台时记录时间,切前台时判断是否超时。 - 避免
Handler内存泄漏:可以使用Handler(Looper.getMainLooper()).apply { postDelayed(...) },或者改用Coroutine的delay替代Handler。
内容的提问来源于stack exchange,提问作者Dre
相关产品推荐
相关产品推荐

