⏱️ Timer
Uniwersalny system timerów - countdown, stopwatch, cooldown, interval.
Przegląd
Moduł Timer zapewnia kompleksowy system timerów przydatny dla:
- Cooldownów reklam
- Czasowych wyzwań gamifikacji
- Odliczania w onboardingu
- Sesji czasowych
- Automatycznych akcji
Countdown (odliczanie)
Podstawowe odliczanie
// Proste odliczanie 60 sekund
ADict.Timer.countdown(
id = "offer_expires",
durationMs = 60_000L,
onTick = { remainingMs ->
val seconds = remainingMs / 1000
tvCountdown.text = "Pozostało: ${seconds}s"
},
onFinish = {
hideOffer()
showExpiredMessage()
}
)
Kontrola countdown
// Pauza
ADict.Timer.pauseCountdown("offer_expires")
// Wznowienie
ADict.Timer.resumeCountdown("offer_expires")
// Anulowanie
ADict.Timer.cancelCountdown("offer_expires")
// Sprawdź pozostały czas
val remaining = ADict.Timer.getCountdownRemaining("offer_expires")
// Czy aktywny
val isActive = ADict.Timer.isCountdownActive("offer_expires")
Obserwowanie stanu (Flow)
lifecycleScope.launch {
ADict.Timer.getCountdownFlow("offer_expires").collect { state ->
when (state) {
is TimerState.Running -> {
progressBar.progress = (state.progress * 100).toInt()
tvTime.text = formatTime(state.remainingMs)
}
is TimerState.Paused -> {
showPausedUI()
}
is TimerState.Finished -> {
showFinishedUI()
}
is TimerState.Cancelled -> {
hideTimerUI()
}
is TimerState.Idle -> {
// Nie uruchomiony
}
}
}
}
Stopwatch (stoper)
Podstawowy stoper
// Start stopera
ADict.Timer.startStopwatch("session_time")
// Pobierz aktualny czas
val elapsed = ADict.Timer.getElapsed("session_time")
Log.d("Timer", "Czas sesji: ${elapsed}ms")
// Pauza
ADict.Timer.pauseStopwatch("session_time")
// Wznów
ADict.Timer.resumeStopwatch("session_time")
// Reset (bez zatrzymywania)
ADict.Timer.resetStopwatch("session_time")
// Stop i pobierz całkowity czas
val totalTime = ADict.Timer.stopStopwatch("session_time")
Obserwowanie stopera
lifecycleScope.launch {
ADict.Timer.getStopwatchFlow("session_time").collect { elapsedMs ->
tvElapsed.text = ADict.Timer.formatTime(elapsedMs, TimeFormat.HH_MM_SS)
}
}
Cooldown
System cooldownów do ograniczania częstotliwości akcji (np. reklamy, przyciski).
// Sprawdź czy akcja dostępna i uruchom cooldown
fun showRewardedAd() {
if (ADict.Timer.isCooldownReady("ad_request")) {
// Pokaż reklamę
loadAndShowAd()
// Rozpocznij 30-sekundowy cooldown
ADict.Timer.startCooldown("ad_request", 30_000L)
} else {
val remaining = ADict.Timer.getCooldownRemaining("ad_request")
val seconds = remaining / 1000
showMessage("Poczekaj jeszcze ${seconds} sekund")
}
}
// Anuluj cooldown (np. po zakupie premium)
ADict.Timer.cancelCooldown("ad_request")
Przykład: Przycisk z cooldownem
class CooldownButton(context: Context) : AppCompatButton(context) {
private val cooldownId = "button_${hashCode()}"
init {
setOnClickListener {
if (ADict.Timer.isCooldownReady(cooldownId)) {
performAction()
ADict.Timer.startCooldown(cooldownId, 5_000L)
startCooldownUI()
}
}
}
private fun startCooldownUI() {
isEnabled = false
ADict.Timer.countdown(
id = "${cooldownId}_ui",
durationMs = 5_000L,
onTick = { remaining ->
text = "Czekaj (${remaining / 1000}s)"
},
onFinish = {
text = "Kliknij"
isEnabled = true
}
)
}
}
Interval (powtarzający się timer)
// Heartbeat co 5 sekund
ADict.Timer.interval(
id = "heartbeat",
intervalMs = 5_000L,
initialDelayMs = 0L
) {
sendHeartbeat()
}
// Auto-save co minutę
ADict.Timer.interval(
id = "auto_save",
intervalMs = 60_000L,
initialDelayMs = 10_000L // zacznij po 10s
) {
saveDocument()
}
// Zatrzymaj interval
ADict.Timer.cancelInterval("heartbeat")
Formatowanie czasu
val ms = 125_500L // 2 min 5.5 sek
// Różne formaty
ADict.Timer.formatTime(ms, TimeFormat.SS) // "125"
ADict.Timer.formatTime(ms, TimeFormat.MM_SS) // "02:05"
ADict.Timer.formatTime(ms, TimeFormat.HH_MM_SS) // "00:02:05"
ADict.Timer.formatTime(ms, TimeFormat.MM_SS_MS) // "02:05.500"
Opóźnione wykonanie
// Proste opóźnienie (one-shot)
ADict.Timer.delay(2_000L) {
showWelcomeMessage()
}
// Opóźnienie z ID (anulowalny)
ADict.Timer.delayWithId("welcome", 3_000L) {
showTutorial()
}
Czyszczenie
// W onDestroy Activity/Fragment
override fun onDestroy() {
super.onDestroy()
// Wyczyść wszystkie timery
ADict.Timer.clearAll()
// Lub selektywnie
ADict.Timer.cancelCountdown("my_timer")
ADict.Timer.stopStopwatch("session")
ADict.Timer.cancelInterval("heartbeat")
}
Przykład: Gra z limitem czasu
class GameActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
startGame()
}
private fun startGame() {
// Rozpocznij sesję gry
ADict.Timer.startStopwatch("game_session")
// Limit czasu 2 minuty
ADict.Timer.countdown(
id = "game_timer",
durationMs = 120_000L,
tickIntervalMs = 100L,
onTick = { remaining ->
tvTimer.text = ADict.Timer.formatTime(remaining, TimeFormat.MM_SS_MS)
// Efekt wizualny gdy mało czasu
if (remaining < 10_000L) {
tvTimer.setTextColor(Color.RED)
}
},
onFinish = {
endGame()
}
)
}
private fun pauseGame() {
ADict.Timer.pauseCountdown("game_timer")
ADict.Timer.pauseStopwatch("game_session")
showPauseMenu()
}
private fun resumeGame() {
ADict.Timer.resumeCountdown("game_timer")
ADict.Timer.resumeStopwatch("game_session")
hidePauseMenu()
}
private fun endGame() {
val totalTime = ADict.Timer.stopStopwatch("game_session")
showResults(score, totalTime)
}
override fun onDestroy() {
super.onDestroy()
ADict.Timer.cancelCountdown("game_timer")
ADict.Timer.stopStopwatch("game_session")
}
}