为了稍微简化问题,我想在应用程序运行时运行多个计时器(并在应用程序重新打开时更新这些计时器)。如果你知道什么是放置游戏,那就是我试图实现的目标,或者甚至只是能够运行多个闹钟可能是非常相似的代码。
每次创建一个新的数据对象(存储在我的本地 Room DB 中)时,都应该创建一个从任意数字(比如 100)开始倒计时的新计时器。
对于每个新对象,该计时器应该保持唯一,因此如果您创建了 3 个计时器,它们都应该独立运行。
当他们达到 0 时,无论你在哪个屏幕或活动上,他们都应该触发数据库调用来做一些工作(不管是什么),然后(这是我最坚持的部分)无需用户交互即可动态更新 UI。
所以用户点击了几次按钮:
我也希望计时器能够在用户不在应用程序上时运行,或者至少在用户回来时更新。这不是绝对必要的,因为我可以通过检查当前时间、存储开始时间和结束时间来做到这一点,但我不确定这是最好的模式。
我尝试使用 WorkManager 来完成此操作,但无法使 UI 正确更新,而且我不完全确定我正在运行多个 UNIQUE 计时器,因为 WorkManager 似乎有点难以调试
实现此目的的一种方法是在您的 Android 应用程序中结合使用计时器和处理程序。
可以为每个新对象创建一个Timer,并将其引用存储在一个以对象的唯一标识为键的HashMap中。这样,您可以在需要时独立访问每个计时器。
在每个 Timer 的任务中,您可以将倒计时值减 1,并使用 Handler 更新 UI。您可以使用 Handler 的 postDelayed() 方法每秒更新一次 UI。这样,用户界面将在没有任何用户交互的情况下即时更新。
当计时器达到 0 时,您可以触发数据库调用来做一些工作并相应地更新 UI。
要处理应用程序未激活的情况,您可以使用 Android 的 AlarmManager 安排一个广播来唤醒您的应用程序并触发必要的操作。
这里有一些示例代码可以帮助您入门:
// Create a HashMap to store Timers
val timers = HashMap<Long, Timer>()
// Create a Timer for each new object
fun createTimer(id: Long, countdown: Int) {
val timer = Timer()
timer.scheduleAtFixedRate(object : TimerTask() {
var remainingTime = countdown
override fun run() {
remainingTime--
// Update the UI using a Handler
val handler = Handler(Looper.getMainLooper())
handler.postDelayed({
// Update UI
updateUI(id, remainingTime)
// Trigger DB call and update UI when timer reaches 0
if (remainingTime == 0) {
doDBWork(id)
updateUIAfterWork(id)
cancelTimer(id)
}
}, 1000)
}
}, 0, 1000)
timers[id] = timer
}
// Cancel a Timer when required
fun cancelTimer(id: Long) {
timers[id]?.cancel()
timers.remove(id)
}
// Update the UI with the remaining time for a given object
fun updateUI(id: Long, remainingTime: Int) {
// Update the UI for the given object
}
// Update the UI after the DB work is done for a given object
fun updateUIAfterWork(id: Long) {
// Update the UI for the given object after DB work is done
}
// Trigger the DB work for a given object
fun doDBWork(id: Long) {
// Trigger the DB work for the given object
}