From ba9315fcd1544046cb6047633280dccbb6c2a953 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Sun, 20 Aug 2023 16:37:49 -0400 Subject: [PATCH] Moves coroutines of BundledUpdate and BundledInsert to a managed model. --- .../com/vitorpamplona/amethyst/model/Note.kt | 15 +++++++++++++++ .../com/vitorpamplona/amethyst/model/User.kt | 17 +++++++++++++++++ .../amethyst/service/NostrDataSource.kt | 1 + .../amethyst/ui/components/BundledUpdate.kt | 15 ++++++++++++++- .../amethyst/ui/note/UserReactionsRow.kt | 1 + .../amethyst/ui/screen/CardFeedViewModel.kt | 2 ++ .../amethyst/ui/screen/FeedViewModel.kt | 2 ++ .../amethyst/ui/screen/LnZapFeedViewModel.kt | 1 + .../amethyst/ui/screen/RelayFeedView.kt | 5 +++++ .../amethyst/ui/screen/UserFeedViewModel.kt | 1 + .../amethyst/ui/screen/loggedIn/SearchScreen.kt | 5 +++++ 11 files changed, 64 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/Note.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/Note.kt index 67a9f626c..855e2ed2b 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/Note.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/Note.kt @@ -615,6 +615,7 @@ open class Note(val idHex: String) { fun clearLive() { if (liveSet != null && liveSet?.isInUse() == false) { + liveSet?.destroy() liveSet = null } } @@ -656,12 +657,26 @@ class NoteLiveSet(u: Note) { relays.hasObservers() || zaps.hasObservers() } + + fun destroy() { + metadata.destroy() + reactions.destroy() + boosts.destroy() + replies.destroy() + reports.destroy() + relays.destroy() + zaps.destroy() + } } class NoteLiveData(val note: Note) : LiveData(NoteState(note)) { // Refreshes observers in batches. private val bundler = BundledUpdate(500, Dispatchers.IO) + fun destroy() { + bundler.cancel() + } + fun invalidateData() { if (!hasObservers()) return diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/User.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/User.kt index ff33dccb1..f2ee77c99 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/User.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/User.kt @@ -372,6 +372,7 @@ class User(val pubkeyHex: String) { fun clearLive() { if (liveSet != null && liveSet?.isInUse() == false) { + liveSet?.destroy() liveSet = null } } @@ -400,6 +401,18 @@ class UserLiveSet(u: User) { zaps.hasObservers() || bookmarks.hasObservers() } + + fun destroy() { + follows.destroy() + followers.destroy() + reports.destroy() + messages.destroy() + relays.destroy() + relayInfo.destroy() + metadata.destroy() + zaps.destroy() + bookmarks.destroy() + } } @Immutable @@ -470,6 +483,10 @@ class UserLiveData(val user: User) : LiveData(UserState(user)) { // Refreshes observers in batches. private val bundler = BundledUpdate(500, Dispatchers.IO) + fun destroy() { + bundler.cancel() + } + fun invalidateData() { if (!hasObservers()) return checkNotInMainThread() diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrDataSource.kt index f403aaab3..0c4e6fb31 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrDataSource.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrDataSource.kt @@ -76,6 +76,7 @@ abstract class NostrDataSource(val debugName: String) { fun destroy() { stop() Client.unsubscribe(clientListener) + bundler.cancel() } open fun start() { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/BundledUpdate.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/BundledUpdate.kt index 890704ae7..f5e702150 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/BundledUpdate.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/BundledUpdate.kt @@ -7,6 +7,8 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.NonCancellable +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.cancel import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -21,6 +23,8 @@ class BundledUpdate( val delay: Long, val dispatcher: CoroutineDispatcher = Dispatchers.Default ) { + val scope = CoroutineScope(dispatcher + SupervisorJob()) + private var onlyOneInBlock = AtomicBoolean() private var invalidatesAgain = false @@ -32,7 +36,6 @@ class BundledUpdate( return } - val scope = CoroutineScope(Job() + dispatcher) scope.launch { try { onUpdate() @@ -48,6 +51,10 @@ class BundledUpdate( } } } + + fun cancel() { + scope.cancel() + } } /** @@ -58,6 +65,8 @@ class BundledInsert( val delay: Long, val dispatcher: CoroutineDispatcher = Dispatchers.Default ) { + val scope = CoroutineScope(dispatcher + SupervisorJob()) + private var onlyOneInBlock = AtomicBoolean() private var queue = LinkedBlockingQueue() @@ -88,4 +97,8 @@ class BundledInsert( } } } + + fun cancel() { + scope.cancel() + } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserReactionsRow.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserReactionsRow.kt index 97c7ce8c2..68e7b267b 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserReactionsRow.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserReactionsRow.kt @@ -326,6 +326,7 @@ class UserReactionsViewModel(val account: Account) : ViewModel() { override fun onCleared() { collectorJob?.cancel() + bundlerInsert.cancel() super.onCleared() } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/CardFeedViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/CardFeedViewModel.kt index 0e5cdef3b..1133fc121 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/CardFeedViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/CardFeedViewModel.kt @@ -353,6 +353,8 @@ open class CardFeedViewModel(val localFilter: FeedFilter) : ViewModel() { override fun onCleared() { clear() + bundlerInsert.cancel() + bundler.cancel() collectorJob?.cancel() super.onCleared() } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedViewModel.kt index b12369b6c..4a02d8f93 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedViewModel.kt @@ -340,6 +340,8 @@ abstract class FeedViewModel(val localFilter: FeedFilter) : ViewModel(), I } override fun onCleared() { + bundlerInsert.cancel() + bundler.cancel() collectorJob?.cancel() super.onCleared() } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/LnZapFeedViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/LnZapFeedViewModel.kt index 45a766158..b9494a78c 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/LnZapFeedViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/LnZapFeedViewModel.kt @@ -96,6 +96,7 @@ open class LnZapFeedViewModel(val dataSource: FeedFilter) : View } override fun onCleared() { + bundler.cancel() collectorJob?.cancel() super.onCleared() } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/RelayFeedView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/RelayFeedView.kt index 498ebc65c..f41eb6f7f 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/RelayFeedView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/RelayFeedView.kt @@ -91,6 +91,11 @@ class RelayFeedViewModel : ViewModel() { refreshSuspended() } } + + override fun onCleared() { + bundler.cancel() + super.onCleared() + } } @OptIn(ExperimentalMaterialApi::class) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/UserFeedViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/UserFeedViewModel.kt index a31a8a5cf..d2ca45832 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/UserFeedViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/UserFeedViewModel.kt @@ -125,6 +125,7 @@ open class UserFeedViewModel(val dataSource: FeedFilter) : ViewModel(), In } override fun onCleared() { + bundler.cancel() collectorJob?.cancel() super.onCleared() } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/SearchScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/SearchScreen.kt index acf734db7..49acad049 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/SearchScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/SearchScreen.kt @@ -195,6 +195,11 @@ class SearchBarViewModel(val account: Account) : ViewModel() { } } + override fun onCleared() { + bundler.cancel() + super.onCleared() + } + fun isSearchingFun() = searchValue.isNotBlank() class Factory(val account: Account) : ViewModelProvider.Factory {