Skip to content

Commit 2ca893e

Browse files
david-allisonlukstbit
authored andcommitted
fix(deck-picker): ANR during syncing
**Issue** * Sync * Background app * Resume app * ANR This is caused by `updateDeckList` being called on the main thread and `isOpenUnsafe` blocking until the sync completed, blocking the main thread. **Fix** * Launch `updateDeckList` on the background thread so it does not ANR * Add TODOs to avoid calling the method entirely Fixes 18886
1 parent 319c915 commit 2ca893e

File tree

2 files changed

+18
-13
lines changed

2 files changed

+18
-13
lines changed

AnkiDroid/src/main/java/com/ichi2/anki/deckpicker/DeckPickerViewModel.kt

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -303,24 +303,28 @@ class DeckPickerViewModel :
303303
*
304304
* This method also triggers an update for the widget to reflect the newly calculated counts.
305305
*/
306+
// TODO: this should not be executed if syncing - called after sync is completed
306307
@RustCleanup("backup with 5 minute timer, instead of deck list refresh")
307-
fun updateDeckList(): Job? {
308-
if (!CollectionManager.isOpenUnsafe()) {
309-
return null
310-
}
311-
if (Build.FINGERPRINT != "robolectric") {
312-
// uses user's desktop settings to determine whether a backup
313-
// actually happens
314-
launchCatchingIO { performBackupInBackground() }
308+
fun updateDeckList(): Job =
309+
viewModelScope.launch(Dispatchers.IO) {
310+
// WARN: On a regular sync, this blocks until the sync completes
311+
// On a full sync, the collection is closed
312+
if (!CollectionManager.isOpenUnsafe()) {
313+
return@launch
314+
}
315+
if (Build.FINGERPRINT != "robolectric") {
316+
// uses user's desktop settings to determine whether a backup
317+
// actually happens
318+
launchCatchingIO { performBackupInBackground() }
319+
}
320+
Timber.d("updateDeckList")
321+
reloadDeckCounts().join()
315322
}
316-
Timber.d("updateDeckList")
317-
return reloadDeckCounts()
318-
}
319323

320-
fun reloadDeckCounts(): Job? {
324+
fun reloadDeckCounts(): Job {
321325
loadDeckCounts?.cancel()
322326
val loadDeckCounts =
323-
viewModelScope.launch {
327+
viewModelScope.launch(Dispatchers.IO) {
324328
Timber.d("Refreshing deck list")
325329
val (deckDueTree, collectionHasNoCards) =
326330
withCol {

AnkiDroid/src/test/java/com/ichi2/anki/DeckPickerTest.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,7 @@ class DeckPickerTest : RobolectricTest() {
648648
deckToClick.performLongClick()
649649

650650
// ASSERT
651+
advanceRobolectricLooper() // ensure that 'focusedDeck' is current
651652
assertThat("unbury is visible: one card is buried", col.sched.haveBuried())
652653
assertThat("deck focus has changed", viewModel.focusedDeck, equalTo(deckWithCards))
653654
}

0 commit comments

Comments
 (0)