mirror of
https://github.com/SimpleMobileTools/Simple-Clock.git
synced 2025-04-03 05:11:09 +02:00
Merge pull request #499 from fatihergin/fix/ISSUE-423-stopwatch-is-not-accurate
replace handler with timer for stopwatch tasks
This commit is contained in:
commit
1754a7233c
@ -199,13 +199,17 @@ class StopwatchFragment : Fragment() {
|
||||
|
||||
private val updateListener = object : Stopwatch.UpdateListener {
|
||||
override fun onUpdate(totalTime: Long, lapTime: Long, useLongerMSFormat: Boolean) {
|
||||
updateDisplayedText(totalTime, lapTime, useLongerMSFormat)
|
||||
activity?.run {
|
||||
updateDisplayedText(totalTime, lapTime, useLongerMSFormat)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStateChanged(state: Stopwatch.State) {
|
||||
updateIcons(state)
|
||||
binding.stopwatchLap.beVisibleIf(state == Stopwatch.State.RUNNING)
|
||||
binding.stopwatchReset.beVisibleIf(state != Stopwatch.State.STOPPED)
|
||||
activity?.run {
|
||||
updateIcons(state)
|
||||
binding.stopwatchLap.beVisibleIf(state == Stopwatch.State.RUNNING)
|
||||
binding.stopwatchReset.beVisibleIf(state != Stopwatch.State.STOPPED)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,16 @@
|
||||
package com.simplemobiletools.clock.helpers
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.os.SystemClock
|
||||
import com.simplemobiletools.clock.models.Lap
|
||||
import java.util.Timer
|
||||
import java.util.TimerTask
|
||||
import java.util.concurrent.CopyOnWriteArraySet
|
||||
|
||||
private const val UPDATE_INTERVAL = 10L
|
||||
|
||||
object Stopwatch {
|
||||
|
||||
private val updateHandler = Handler(Looper.getMainLooper())
|
||||
private var updateTimer = Timer()
|
||||
private var uptimeAtStart = 0L
|
||||
private var totalTicks = 0
|
||||
private var currentTicks = 0 // ticks that reset at pause
|
||||
@ -27,7 +27,7 @@ object Stopwatch {
|
||||
private var updateListeners = CopyOnWriteArraySet<UpdateListener>()
|
||||
|
||||
fun reset() {
|
||||
updateHandler.removeCallbacksAndMessages(null)
|
||||
updateTimer.cancel()
|
||||
state = State.STOPPED
|
||||
currentTicks = 0
|
||||
totalTicks = 0
|
||||
@ -39,7 +39,7 @@ object Stopwatch {
|
||||
fun toggle(setUptimeAtStart: Boolean) {
|
||||
if (state != State.RUNNING) {
|
||||
state = State.RUNNING
|
||||
updateHandler.post(updateRunnable)
|
||||
updateTimer = buildUpdateTimer()
|
||||
if (setUptimeAtStart) {
|
||||
uptimeAtStart = SystemClock.uptimeMillis()
|
||||
}
|
||||
@ -47,7 +47,7 @@ object Stopwatch {
|
||||
state = State.PAUSED
|
||||
val prevSessionsMS = (totalTicks - currentTicks) * UPDATE_INTERVAL
|
||||
val totalDuration = SystemClock.uptimeMillis() - uptimeAtStart + prevSessionsMS
|
||||
updateHandler.removeCallbacksAndMessages(null)
|
||||
updateTimer.cancel()
|
||||
currentTicks = 0
|
||||
totalTicks--
|
||||
for (listener in updateListeners) {
|
||||
@ -97,23 +97,26 @@ object Stopwatch {
|
||||
updateListeners.remove(updateListener)
|
||||
}
|
||||
|
||||
private val updateRunnable = object : Runnable {
|
||||
override fun run() {
|
||||
if (state == State.RUNNING) {
|
||||
if (totalTicks % 10 == 0) {
|
||||
for (listener in updateListeners) {
|
||||
listener.onUpdate(
|
||||
totalTicks * UPDATE_INTERVAL,
|
||||
lapTicks * UPDATE_INTERVAL,
|
||||
false
|
||||
)
|
||||
private fun buildUpdateTimer(): Timer {
|
||||
return Timer().apply {
|
||||
scheduleAtFixedRate(object : TimerTask() {
|
||||
override fun run() {
|
||||
if (state == State.RUNNING) {
|
||||
if (totalTicks % 10 == 0) {
|
||||
for (listener in updateListeners) {
|
||||
listener.onUpdate(
|
||||
totalTicks * UPDATE_INTERVAL,
|
||||
lapTicks * UPDATE_INTERVAL,
|
||||
false
|
||||
)
|
||||
}
|
||||
}
|
||||
totalTicks++
|
||||
currentTicks++
|
||||
lapTicks++
|
||||
}
|
||||
}
|
||||
totalTicks++
|
||||
currentTicks++
|
||||
lapTicks++
|
||||
updateHandler.postAtTime(this, uptimeAtStart + currentTicks * UPDATE_INTERVAL)
|
||||
}
|
||||
}, 0, UPDATE_INTERVAL)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ import android.os.Handler
|
||||
import android.os.IBinder
|
||||
import android.os.Looper
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.ServiceCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.simplemobiletools.clock.R
|
||||
import com.simplemobiletools.clock.extensions.getFormattedDuration
|
||||
@ -18,7 +19,6 @@ import com.simplemobiletools.clock.helpers.Stopwatch
|
||||
import com.simplemobiletools.clock.helpers.Stopwatch.State
|
||||
import com.simplemobiletools.clock.helpers.Stopwatch.UpdateListener
|
||||
import com.simplemobiletools.commons.extensions.showErrorToast
|
||||
import com.simplemobiletools.commons.helpers.isNougatPlus
|
||||
import com.simplemobiletools.commons.helpers.isOreoPlus
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
@ -54,15 +54,15 @@ class StopwatchService : Service() {
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
bus.unregister(this)
|
||||
Stopwatch.removeUpdateListener(updateListener)
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onMessageEvent(event: StopwatchStopService) {
|
||||
isStopping = true
|
||||
stopForeground(true)
|
||||
stopForegroundService()
|
||||
}
|
||||
|
||||
private fun getServiceNotificationBuilder(
|
||||
@ -98,17 +98,29 @@ class StopwatchService : Service() {
|
||||
}
|
||||
|
||||
private val updateListener = object : UpdateListener {
|
||||
private val MIN_NOTIFICATION_UPDATE_INTERVAL = 500L
|
||||
private var lastUpdateTime = 0L
|
||||
override fun onUpdate(totalTime: Long, lapTime: Long, useLongerMSFormat: Boolean) {
|
||||
if (!isStopping) {
|
||||
if (!isStopping && shouldNotificationBeUpdated()) {
|
||||
lastUpdateTime = System.currentTimeMillis()
|
||||
updateNotification(totalTime)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStateChanged(state: State) {
|
||||
if (state == State.STOPPED && isNougatPlus()) {
|
||||
stopForeground(STOP_FOREGROUND_REMOVE)
|
||||
if (state == State.STOPPED) {
|
||||
stopForegroundService()
|
||||
}
|
||||
}
|
||||
|
||||
private fun shouldNotificationBeUpdated(): Boolean {
|
||||
return (System.currentTimeMillis() - lastUpdateTime) > MIN_NOTIFICATION_UPDATE_INTERVAL
|
||||
}
|
||||
}
|
||||
|
||||
private fun stopForegroundService() {
|
||||
ServiceCompat.stopForeground(this@StopwatchService, ServiceCompat.STOP_FOREGROUND_REMOVE)
|
||||
stopSelf()
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user