如何实现因不活动而导致的超时操作

How to implement a timeout action due to inactivity

假设我有一个动作要在用户不触摸屏幕一段时间后执行。我如何实现一个计时器,它在超时时执行操作,但在每次用户触摸屏幕时重新开始?

我搜索了几个答案,但没有找到像我想要的解决方案一样简单的解决方案。这是对我有用的:

我使用了在 onCreate() 中启动并在 onDestroy() 中取消的 onUserInteraction() function, which is called every time the user touches the screen. I declared a CountDownTimer。每次调用 onUserInteraction() 时,CountDownTimer 都会被取消、重置,然后再次启动。当 CountDownTimer 完成时,执行操作。

package com.example.inactivityapp

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.CountDownTimer
import android.util.Log
import android.widget.Toast

private val TAG = InactivityActivity::class.java.simpleName

private const val INACTIVITY_SECONDS: Int = 5

class InactivityActivity : AppCompatActivity() {

    var inactivitySeconds = INACTIVITY_SECONDS

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_inactivity)

        inactivityCountDownTimer.start()

    }

    override fun onDestroy() {
        super.onDestroy()
        inactivityCountDownTimer.cancel()
    }

    override fun onUserInteraction() {
        super.onUserInteraction()
        Log.i(TAG, "user interaction")
        inactivityCountDownTimer.cancel()
        inactivitySeconds = INACTIVITY_SECONDS
        inactivityCountDownTimer.start()
    }

    var inactivityCountDownTimer =
        object : CountDownTimer(inactivitySeconds * 1000.toLong(), 1000) {
            override fun onTick(millisUntilFinished: Long) {
                Log.i(TAG, inactivitySeconds.toString())
                inactivitySeconds--
            }

            override fun onFinish() {
                Toast.makeText(
                    this@InactivityActivity,
                    "Activity Timeout: Perform timeout task",
                    Toast.LENGTH_LONG
                ).show()
                Log.i(TAG, "activity timeout")
            }
        }
}

这是一个未经测试的协程想法:

private const val INACTIVITY_SECONDS: Int = 5

abstract class InactivityActivity : AppCompatActivity() {

    private val counterScope = CoroutineScope(Dispatchers.Main)

    private fun restartCountDown() {
        counterScope.cancel()
        counterScope.launch {
            delay(INACTIVITY_SECONDS * 1000L)
            onInactivity()
        }
    }

    protected abstract fun onInactivity()

    override fun onPause() {
        super.onPause()
        counterScope.cancel()
    }

    override fun onResume() {
        super.onResume()
        restartCountDown()
    }

    override fun onUserInteraction() {
        super.onUserInteraction()
        restartCountDown()
    }
}