Skip to content

Commit 823d6aa

Browse files
committed
Use GlobalScope instead of NonCancellable to set items state in ItemScreenModel
1 parent d15d35b commit 823d6aa

File tree

1 file changed

+24
-17
lines changed

1 file changed

+24
-17
lines changed

app/src/main/java/com/readrops/app/item/ItemScreenModel.kt

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,9 @@ import com.readrops.db.pojo.ItemWithFeed
4040
import com.readrops.db.queries.ItemSelectionQueryBuilder
4141
import com.readrops.db.queries.ItemsQueryBuilder
4242
import kotlinx.coroutines.CoroutineDispatcher
43+
import kotlinx.coroutines.DelicateCoroutinesApi
4344
import kotlinx.coroutines.Dispatchers
44-
import kotlinx.coroutines.NonCancellable
45+
import kotlinx.coroutines.GlobalScope
4546
import kotlinx.coroutines.flow.Flow
4647
import kotlinx.coroutines.flow.MutableStateFlow
4748
import kotlinx.coroutines.flow.SharingStarted
@@ -51,7 +52,6 @@ import kotlinx.coroutines.flow.map
5152
import kotlinx.coroutines.flow.stateIn
5253
import kotlinx.coroutines.flow.update
5354
import kotlinx.coroutines.launch
54-
import kotlinx.coroutines.withContext
5555
import org.koin.core.component.KoinComponent
5656
import org.koin.core.component.get
5757
import org.koin.core.parameter.parametersOf
@@ -92,6 +92,7 @@ class ItemScreenModel(
9292
)
9393
)
9494
)
95+
9596
// based type is Flow because with StateFlow when coming back from process death, pager doesn't resume
9697
// it might be due to stateIn() overlapping cachedIn(), but not sure
9798
var itemState: Flow<PagingData<ItemWithFeed>> = _itemState.asStateFlow()
@@ -360,23 +361,29 @@ class ItemScreenModel(
360361
item, context, useCustomShareIntentTpl.value, customShareIntentTpl.value
361362
)
362363

364+
@OptIn(DelicateCoroutinesApi::class)
363365
override fun onDispose() {
364-
screenModelScope.launch(dispatcher) {
365-
withContext(NonCancellable) {
366-
repository.setItemsRead(
367-
items = state.value.stateChanges
368-
.filter { it.readChange }
369-
.map { it.item }
370-
)
366+
// Use GlobalScope instead of NonCancellable
367+
// It seems that NonCancellable is not is sufficiently non cancellable
368+
// I ran multiple times into very frustrating situations where items were not set read
369+
// The risk of leak here is mitigated by the fact that only one shot operations are performed
370+
// If the coroutine is cancelled for whatever reason, only items state will be lost, which is not a big deal
371+
// and should happen very rarely
372+
GlobalScope.launch(dispatcher) {
373+
repository.setItemsRead(
374+
items = state.value.stateChanges
375+
.filter { it.readChange }
376+
.map { it.item }
377+
)
378+
379+
state.value.stateChanges
380+
.filter { it.starChange }
381+
.forEach {
382+
repository.setItemStarState(it.item.apply {
383+
isStarred = !isStarred
384+
})
385+
}
371386

372-
state.value.stateChanges
373-
.filter { it.starChange }
374-
.forEach {
375-
repository.setItemStarState(it.item.apply {
376-
isStarred = !isStarred
377-
})
378-
}
379-
}
380387
}
381388
}
382389
}

0 commit comments

Comments
 (0)