Kotlin Android实现60秒用户无活动检测及代码问题排查
Android应用内持续无活动检测解决方案
原代码存在的问题
- 无活动提示触发后计时器不会重启,只能完成一次检测
onTouchEvent仅能监听MainActivity自身的触摸操作,Fragment内的用户触摸不会触发该方法,导致Fragment中操作时计时器无法重置
解决方案实现步骤
- 循环检测逻辑:在无活动提示触发后重新启动计时器,实现持续检测
- 全局触摸捕获:重写
dispatchTouchEvent方法(替代onTouchEvent),该方法能拦截所有分发到Activity及其内部Fragment的触摸事件,确保Fragment内操作也能重置计时器 - 覆盖其他用户操作:重写
onKeyDown方法,捕获按键操作(如返回键、菜单键),同步重置计时器 - 生命周期适配:应用进入后台时停止计时器,回到前台时重启,避免后台误触发;销毁时清理Handler防止内存泄漏
完整代码实现
class MainActivity : AppCompatActivity() { private val inactiveTime = 60000L // 60秒无活动阈值 private lateinit var handler: Handler private lateinit var checkInactiveRunnable: Runnable // 无活动提示布局(需在布局文件中定义,初始设为GONE) private lateinit var inactiveTipLayout: View override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) inactiveTipLayout = findViewById(R.id.inactive_tip_layout) // 初始化Handler与循环检测任务 handler = Handler(Looper.getMainLooper()) checkInactiveRunnable = Runnable { showInactiveTip() startInactiveCheck() // 触发提示后重启检测 } startInactiveCheck() // 启动首次检测 } private fun startInactiveCheck() { handler.postDelayed(checkInactiveRunnable, inactiveTime) } private fun stopInactiveCheck() { handler.removeCallbacks(checkInactiveRunnable) inactiveTipLayout.visibility = View.GONE } private fun showInactiveTip() { inactiveTipLayout.visibility = View.VISIBLE Log.d("InactiveCheck", "用户已无活动60秒") // 可在此添加弹窗、震动等提示逻辑 } // 拦截所有触摸事件(包括Fragment内操作) override fun dispatchTouchEvent(ev: MotionEvent): Boolean { if (ev.action == MotionEvent.ACTION_DOWN) { stopInactiveCheck() startInactiveCheck() } return super.dispatchTouchEvent(ev) } // 捕获按键操作,重置计时器 override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { stopInactiveCheck() startInactiveCheck() return super.onKeyDown(keyCode, event) } // 后台时停止检测 override fun onPause() { super.onPause() stopInactiveCheck() } // 前台时重启检测 override fun onResume() { super.onResume() startInactiveCheck() } // 销毁时清理Handler,避免内存泄漏 override fun onDestroy() { super.onDestroy() handler.removeCallbacksAndMessages(null) } }
补充说明
- 需确保布局文件中存在
inactive_tip_layout,并设置初始可见性为GONE dispatchTouchEvent已覆盖所有触摸相关操作(点击、滑动、长按等),无需额外处理- 若想进一步优化内存泄漏问题,可改用
ViewModel结合Coroutine实现计时器,用delay替代postDelayed,用Job控制启停
内容的提问来源于stack exchange,提问作者Ajith
相关产品推荐
相关产品推荐

