From e8b09a9ba35915a74b1ce22de1bf6cfaa13f7fa7 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Tue, 21 Feb 2023 11:33:28 -0500 Subject: [PATCH] Refactors Notification Cache updates. --- .../amethyst/NotificationCache.kt | 42 ++++++++++++------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/NotificationCache.kt b/app/src/main/java/com/vitorpamplona/amethyst/NotificationCache.kt index a8f5bd4a5..fd386810f 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/NotificationCache.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/NotificationCache.kt @@ -3,11 +3,14 @@ package com.vitorpamplona.amethyst import android.content.Context import androidx.lifecycle.LiveData import com.vitorpamplona.amethyst.model.Note +import java.util.concurrent.atomic.AtomicBoolean import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job +import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.delay import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext object NotificationCache { val lastReadByRoute = mutableMapOf() @@ -20,7 +23,7 @@ object NotificationCache { val scope = CoroutineScope(Job() + Dispatchers.IO) scope.launch { LocalPreferences(context).saveLastRead(route, timestampInSecs) - invalidateData() + live.invalidateData() } } } @@ -36,24 +39,31 @@ object NotificationCache { // Observers line up here. val live: NotificationLiveData = NotificationLiveData(this) - - // Refreshes observers in batches. - var handlerWaiting = false - @Synchronized - fun invalidateData() { - if (handlerWaiting) return - - handlerWaiting = true - val scope = CoroutineScope(Job() + Dispatchers.Default) - scope.launch { - delay(100) - live.refresh() - handlerWaiting = false - } - } } class NotificationLiveData(val cache: NotificationCache): LiveData(NotificationState(cache)) { + // Refreshes observers in batches. + var handlerWaiting = AtomicBoolean() + + @Synchronized + fun invalidateData() { + if (!hasActiveObservers()) return + if (handlerWaiting.getAndSet(true)) return + + handlerWaiting.set(true) + val scope = CoroutineScope(Job() + Dispatchers.Main) + scope.launch { + try { + delay(100) + refresh() + } finally { + withContext(NonCancellable) { + handlerWaiting.set(false) + } + } + } + } + fun refresh() { postValue(NotificationState(cache)) }