mirror of
https://github.com/FossifyOrg/Clock.git
synced 2026-04-18 05:17:02 -04:00
perf: optimize stopwatch updates (#213)
* fix: bump stopwatch update interval to 100ms The UI does not need to update 50 times a second. * perf: optimize stopwatch updates - Added a static id for live lap for cleaner logic - Added `updateLiveLap` method to the stopwatch adapter. This is responsible for updating the live lap and maintaining its position in the list * refactor: move Lap.kt to extensions package
This commit is contained in:
@@ -10,17 +10,22 @@ import org.fossify.clock.extensions.formatStopwatchTime
|
||||
import org.fossify.clock.helpers.SORT_BY_LAP
|
||||
import org.fossify.clock.helpers.SORT_BY_LAP_TIME
|
||||
import org.fossify.clock.helpers.SORT_BY_TOTAL_TIME
|
||||
import org.fossify.clock.extensions.isLive
|
||||
import org.fossify.clock.models.Lap
|
||||
import org.fossify.commons.adapters.MyRecyclerViewAdapter
|
||||
import org.fossify.commons.views.MyRecyclerView
|
||||
|
||||
class StopwatchAdapter(
|
||||
activity: SimpleActivity,
|
||||
var laps: ArrayList<Lap>,
|
||||
private var laps: ArrayList<Lap>,
|
||||
recyclerView: MyRecyclerView,
|
||||
itemClick: (Any) -> Unit,
|
||||
) : MyRecyclerViewAdapter(activity, recyclerView, itemClick) {
|
||||
|
||||
init {
|
||||
recyclerView.itemAnimator = null
|
||||
}
|
||||
|
||||
override fun getActionMenuId() = 0
|
||||
|
||||
override fun prepareActionMode(menu: Menu) {}
|
||||
@@ -60,9 +65,26 @@ class StopwatchAdapter(
|
||||
finishActMode()
|
||||
}
|
||||
|
||||
fun updateLiveLap(totalTime: Long, lapTime: Long) {
|
||||
val oldIndex = laps.indexOfFirst { it.isLive() }
|
||||
if (oldIndex == -1) return
|
||||
laps[oldIndex].lapTime = lapTime
|
||||
laps[oldIndex].totalTime = totalTime
|
||||
laps.sort()
|
||||
|
||||
// the live lap might have changed position
|
||||
val newIndex = laps.indexOfFirst { it.isLive() }
|
||||
if (oldIndex == newIndex) {
|
||||
notifyItemChanged(newIndex)
|
||||
} else {
|
||||
notifyItemMoved(oldIndex, newIndex)
|
||||
notifyItemChanged(newIndex)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupView(view: View, lap: Lap) {
|
||||
ItemLapBinding.bind(view).apply {
|
||||
lapOrder.text = lap.id.toString()
|
||||
lapOrder.text = if (lap.isLive()) laps.size.toString() else lap.id.toString()
|
||||
lapOrder.setTextColor(textColor)
|
||||
lapOrder.setOnClickListener {
|
||||
itemClick(SORT_BY_LAP)
|
||||
|
||||
6
app/src/main/kotlin/org/fossify/clock/extensions/Lap.kt
Normal file
6
app/src/main/kotlin/org/fossify/clock/extensions/Lap.kt
Normal file
@@ -0,0 +1,6 @@
|
||||
package org.fossify.clock.extensions
|
||||
|
||||
import org.fossify.clock.helpers.STOPWATCH_LIVE_LAP_ID
|
||||
import org.fossify.clock.models.Lap
|
||||
|
||||
fun Lap.isLive() = id == STOPWATCH_LIVE_LAP_ID
|
||||
@@ -17,6 +17,7 @@ import org.fossify.clock.extensions.formatStopwatchTime
|
||||
import org.fossify.clock.helpers.SORT_BY_LAP
|
||||
import org.fossify.clock.helpers.SORT_BY_LAP_TIME
|
||||
import org.fossify.clock.helpers.SORT_BY_TOTAL_TIME
|
||||
import org.fossify.clock.helpers.STOPWATCH_LIVE_LAP_ID
|
||||
import org.fossify.clock.helpers.Stopwatch
|
||||
import org.fossify.clock.models.Lap
|
||||
import org.fossify.commons.dialogs.PermissionRequiredDialog
|
||||
@@ -38,7 +39,7 @@ import org.fossify.commons.helpers.SORT_DESCENDING
|
||||
|
||||
class StopwatchFragment : Fragment() {
|
||||
|
||||
lateinit var stopwatchAdapter: StopwatchAdapter
|
||||
private var stopwatchAdapter: StopwatchAdapter? = null
|
||||
private lateinit var binding: FragmentStopwatchBinding
|
||||
|
||||
private var latestLapTime: Long = 0L
|
||||
@@ -129,6 +130,12 @@ class StopwatchFragment : Fragment() {
|
||||
)
|
||||
stopwatchReset.applyColorFilter(requireContext().getProperTextColor())
|
||||
}
|
||||
|
||||
stopwatchAdapter?.apply {
|
||||
updatePrimaryColor()
|
||||
updateBackgroundColor(requireContext().getProperBackgroundColor())
|
||||
updateTextColor(requireContext().getProperTextColor())
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateIcons(state: Stopwatch.State) {
|
||||
@@ -233,37 +240,28 @@ class StopwatchFragment : Fragment() {
|
||||
val allLaps = ArrayList(Stopwatch.laps)
|
||||
if (Stopwatch.laps.isNotEmpty() && Stopwatch.state != Stopwatch.State.STOPPED) {
|
||||
allLaps += Lap(
|
||||
id = Stopwatch.laps.size + 1,
|
||||
id = STOPWATCH_LIVE_LAP_ID,
|
||||
lapTime = latestLapTime,
|
||||
totalTime = latestTotalTime
|
||||
)
|
||||
}
|
||||
|
||||
allLaps.sort()
|
||||
stopwatchAdapter.apply {
|
||||
updatePrimaryColor()
|
||||
updateBackgroundColor(requireContext().getProperBackgroundColor())
|
||||
updateTextColor(requireContext().getProperTextColor())
|
||||
updateItems(allLaps)
|
||||
}
|
||||
stopwatchAdapter?.updateItems(allLaps)
|
||||
}
|
||||
|
||||
private val updateListener = object : Stopwatch.UpdateListener {
|
||||
override fun onUpdate(totalTime: Long, lapTime: Long, useLongerMSFormat: Boolean) {
|
||||
activity?.runOnUiThread {
|
||||
binding.stopwatchTime.text = totalTime.formatStopwatchTime(useLongerMSFormat)
|
||||
latestLapTime = lapTime
|
||||
latestTotalTime = totalTime
|
||||
updateLaps()
|
||||
}
|
||||
binding.stopwatchTime.text = totalTime.formatStopwatchTime(useLongerMSFormat)
|
||||
latestLapTime = lapTime
|
||||
latestTotalTime = totalTime
|
||||
stopwatchAdapter?.updateLiveLap(totalTime, lapTime)
|
||||
}
|
||||
|
||||
override fun onStateChanged(state: Stopwatch.State) {
|
||||
activity?.runOnUiThread {
|
||||
updateIcons(state)
|
||||
binding.stopwatchLap.beVisibleIf(state == Stopwatch.State.RUNNING)
|
||||
binding.stopwatchReset.beVisibleIf(state != Stopwatch.State.STOPPED)
|
||||
}
|
||||
updateIcons(state)
|
||||
binding.stopwatchLap.beVisibleIf(state == Stopwatch.State.RUNNING)
|
||||
binding.stopwatchReset.beVisibleIf(state != Stopwatch.State.STOPPED)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,6 +83,8 @@ const val SORT_BY_LAP = 1
|
||||
const val SORT_BY_LAP_TIME = 2
|
||||
const val SORT_BY_TOTAL_TIME = 4
|
||||
|
||||
const val STOPWATCH_LIVE_LAP_ID = Int.MAX_VALUE
|
||||
|
||||
// alarm and timer sorting
|
||||
const val SORT_BY_CREATION_ORDER = 0
|
||||
const val SORT_BY_ALARM_TIME = 1
|
||||
|
||||
@@ -11,7 +11,7 @@ import kotlinx.coroutines.launch
|
||||
import org.fossify.clock.models.Lap
|
||||
import java.util.concurrent.CopyOnWriteArraySet
|
||||
|
||||
private const val UPDATE_INTERVAL_MS = 20L
|
||||
private const val UPDATE_INTERVAL_MS = 100L
|
||||
|
||||
object Stopwatch {
|
||||
private var startTime = 0L
|
||||
|
||||
Reference in New Issue
Block a user