Skip to content

Commit f51ea46

Browse files
criticalAYdavid-allison
authored andcommitted
refactor: extract 'applicationScope' from AnkiDroidApp to :common:android
1 parent ebcf8e0 commit f51ea46

11 files changed

Lines changed: 58 additions & 32 deletions

File tree

AnkiDroid/src/main/java/com/ichi2/anki/AnkiDroidApp.kt

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import com.ichi2.anki.analytics.UsageAnalytics
3939
import com.ichi2.anki.browser.SharedPreferencesLastDeckIdRepository
4040
import com.ichi2.anki.common.annotations.LegacyNotifications
4141
import com.ichi2.anki.common.annotations.NeedsTest
42+
import com.ichi2.anki.common.coroutines.applicationScope
4243
import com.ichi2.anki.common.crashreporting.CrashReportService.sendExceptionReport
4344
import com.ichi2.anki.common.utils.annotation.KotlinCleanup
4445
import com.ichi2.anki.compat.CompatHelper
@@ -69,9 +70,6 @@ import com.ichi2.widget.DayRolloverAlarm
6970
import com.ichi2.widget.cardanalysis.CardAnalysisWidget
7071
import com.ichi2.widget.deckpicker.DeckPickerWidget
7172
import com.ichi2.widget.restoreRecurringAlarms
72-
import kotlinx.coroutines.CoroutineScope
73-
import kotlinx.coroutines.Dispatchers
74-
import kotlinx.coroutines.SupervisorJob
7573
import kotlinx.coroutines.launch
7674
import timber.log.Timber
7775
import timber.log.Timber.DebugTree
@@ -377,24 +375,6 @@ open class AnkiDroidApp :
377375
}
378376

379377
companion object {
380-
/**
381-
* [CoroutineScope] tied to the [Application], allowing executing of tasks which should
382-
* execute as long as the app is running
383-
*
384-
* This scope is bound by default to [Dispatchers.Main.immediate][kotlinx.coroutines.MainCoroutineDispatcher.immediate].
385-
* Use an alternate dispatcher if the main thread is not required: [Dispatchers.Default] or [Dispatchers.IO]
386-
*
387-
* This scope will not be cancelled; exceptions are handled by [SupervisorJob]
388-
*
389-
* See: [Operations that shouldn't be cancelled in Coroutines](https://medium.com/androiddevelopers/coroutines-patterns-for-work-that-shouldnt-be-cancelled-e26c40f142ad#d425)
390-
*
391-
* This replicates the manner which `lifecycleScope`/`viewModelScope` is exposed in Android
392-
*/
393-
// lazy init required due to kotlinx-coroutines-test 1.10.0:
394-
// Main was accessed when the platform dispatcher was absent and the test dispatcher
395-
// was unset
396-
val applicationScope by lazy { CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate) }
397-
398378
/**
399379
* A [SharedPreferencesProvider] which does not require [onCreate] when run from tests
400380
*

AnkiDroid/src/main/java/com/ichi2/anki/CoroutineHelpers.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import com.ichi2.anki.CrashReportData.HelpAction.AnkiBackendLink
4242
import com.ichi2.anki.CrashReportData.HelpAction.OpenDeckOptions
4343
import com.ichi2.anki.android.AnkiBroadcastReceiver
4444
import com.ichi2.anki.common.annotations.UseContextParameter
45+
import com.ichi2.anki.common.coroutines.applicationScope
4546
import com.ichi2.anki.common.crashreporting.CrashReportService
4647
import com.ichi2.anki.dialogs.DatabaseErrorDialog
4748
import com.ichi2.anki.dialogs.DatabaseErrorDialog.DatabaseErrorDialogType
@@ -648,7 +649,7 @@ fun AnkiBroadcastReceiver.runGloballyWithTimeout(
648649
return
649650
}
650651

651-
AnkiDroidApp.applicationScope.launch {
652+
applicationScope.launch {
652653
try {
653654
withTimeout(minOf(timeout, 8.seconds)) {
654655
block()

AnkiDroid/src/main/java/com/ichi2/anki/DayRolloverHandler.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import anki.collection.OpChanges
3535
import anki.collection.opChanges
3636
import com.ichi2.anki.CollectionManager.withOpenColOrNull
3737
import com.ichi2.anki.android.AnkiBroadcastReceiver
38+
import com.ichi2.anki.common.coroutines.applicationScope
3839
import com.ichi2.anki.common.crashreporting.CrashReportService
3940
import com.ichi2.anki.exception.ManuallyReportedException
4041
import com.ichi2.anki.libanki.EpochSeconds
@@ -82,7 +83,7 @@ object DayRolloverHandler : AnkiBroadcastReceiver() {
8283
// the outcome would be two calls to notifySubscribers, which is acceptable
8384
Timber.v("received ${intent.action}")
8485
// launch coroutine as we need access to `col.sched`
85-
AnkiDroidApp.applicationScope.launchCatching(Dispatchers.IO, errorMessageHandler = { msg ->
86+
applicationScope.launchCatching(Dispatchers.IO, errorMessageHandler = { msg ->
8687
CrashReportService.sendExceptionReport(
8788
e = ManuallyReportedException(msg),
8889
origin = "DayRolloverHandler::onReceive",

AnkiDroid/src/main/java/com/ichi2/anki/IntentHandler.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import androidx.core.content.FileProvider
2828
import androidx.core.content.IntentCompat
2929
import androidx.work.WorkManager
3030
import com.ichi2.anki.common.annotations.NeedsTest
31+
import com.ichi2.anki.common.coroutines.applicationScope
3132
import com.ichi2.anki.common.utils.trimToLength
3233
import com.ichi2.anki.dialogs.DialogHandler.Companion.storeMessage
3334
import com.ichi2.anki.dialogs.DialogHandlerMessage
@@ -235,7 +236,7 @@ class IntentHandler : AbstractIntentHandler() {
235236
// TODO improve the handling of the imported temporary files
236237
// Launching this scope without tying it to a lifecycle since ,
237238
// IntentHandler finishes quickly, but deletion may still be in progress
238-
AnkiDroidApp.applicationScope.launch(Dispatchers.IO) {
239+
applicationScope.launch(Dispatchers.IO) {
239240
try {
240241
val file = File(path!!)
241242
val fileUri =
@@ -295,7 +296,7 @@ class IntentHandler : AbstractIntentHandler() {
295296
// TODO improve the handling of the imported temporary files
296297
// Launching this scope without tying it to a lifecycle since ,
297298
// IntentHandler finishes quickly, but deletion may still be in progress
298-
AnkiDroidApp.applicationScope.launch(Dispatchers.IO) {
299+
applicationScope.launch(Dispatchers.IO) {
299300
try {
300301
contentResolver.delete(sharedDeckUri, null, null)
301302
Timber.i("onCreate: downloaded shared deck deleted")

AnkiDroid/src/main/java/com/ichi2/anki/TtsVoices.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ package com.ichi2.anki
2424

2525
import android.speech.tts.TextToSpeech
2626
import android.speech.tts.Voice
27+
import com.ichi2.anki.common.coroutines.applicationScope
2728
import com.ichi2.anki.i18n.normalize
2829
import com.ichi2.anki.i18n.toAnkiTwoLetterCode
2930
import com.ichi2.anki.libanki.TemplateManager
@@ -146,7 +147,7 @@ object TtsVoices {
146147
// This is intended to be a global singleton outside the lifecycle of a specific activity
147148
// Most of the time of execution is waiting for the TTS Engine to initialize
148149
buildLocalesJob =
149-
AnkiDroidApp.applicationScope.launch(Dispatchers.IO) {
150+
applicationScope.launch(Dispatchers.IO) {
150151
Timber.d("executing job")
151152
loadTtsVoicesData()
152153
buildLocalesJob = null

AnkiDroid/src/main/java/com/ichi2/utils/ImportUtils.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import com.ichi2.anki.AnkiActivity
3131
import com.ichi2.anki.AnkiDroidApp
3232
import com.ichi2.anki.R
3333
import com.ichi2.anki.common.annotations.NeedsTest
34+
import com.ichi2.anki.common.coroutines.applicationScope
3435
import com.ichi2.anki.common.crashreporting.CrashReportService
3536
import com.ichi2.anki.common.time.TimeManager
3637
import com.ichi2.anki.compat.CompatHelper
@@ -326,7 +327,7 @@ object ImportUtils {
326327
) {
327328
// Use applicationScope: IntentHandler calls this and does not have a lifecycleScope
328329
fun copyDebugInfo(debugInfo: String) =
329-
AnkiDroidApp.applicationScope.launch {
330+
applicationScope.launch {
330331
Timber.i("copying debug info to clipboard")
331332
val stringToCopy =
332333
buildString {

AnkiDroid/src/main/java/com/ichi2/widget/DayRolloverAlarm.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ import androidx.annotation.VisibleForTesting
2626
import androidx.core.app.PendingIntentCompat
2727
import androidx.core.content.getSystemService
2828
import anki.collection.opChanges
29-
import com.ichi2.anki.AnkiDroidApp.Companion.applicationScope
3029
import com.ichi2.anki.CollectionManager.withOpenColOrNull
3130
import com.ichi2.anki.android.AnkiBroadcastReceiver
31+
import com.ichi2.anki.common.coroutines.applicationScope
3232
import com.ichi2.anki.common.crashreporting.CrashReportService
3333
import com.ichi2.anki.common.time.TimeManager
3434
import com.ichi2.anki.exception.ManuallyReportedException

AnkiDroid/src/main/java/com/ichi2/widget/cardanalysis/CardAnalysisWidget.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ import android.content.Context
2424
import android.content.Intent
2525
import android.view.View
2626
import android.widget.RemoteViews
27-
import com.ichi2.anki.AnkiDroidApp
2827
import com.ichi2.anki.IntentHandler.Companion.intentToReviewDeckFromShortcuts
2928
import com.ichi2.anki.R
3029
import com.ichi2.anki.analytics.UsageAnalytics
30+
import com.ichi2.anki.common.coroutines.applicationScope
3131
import com.ichi2.anki.common.crashreporting.CrashReportService
3232
import com.ichi2.anki.isCollectionEmpty
3333
import com.ichi2.anki.libanki.DeckId
@@ -89,7 +89,7 @@ class CardAnalysisWidget : AnalyticsWidgetProvider() {
8989
return
9090
}
9191

92-
AnkiDroidApp.applicationScope.launch {
92+
applicationScope.launch {
9393
val isCollectionEmpty = isCollectionEmpty()
9494
if (isCollectionEmpty) {
9595
showCollectionDeck(context, appWidgetManager, appWidgetId, remoteViews)

AnkiDroid/src/main/java/com/ichi2/widget/deckpicker/DeckPickerWidget.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ import android.content.Context
2424
import android.content.Intent
2525
import android.view.View
2626
import android.widget.RemoteViews
27-
import com.ichi2.anki.AnkiDroidApp
2827
import com.ichi2.anki.CollectionManager.withCol
2928
import com.ichi2.anki.IntentHandler.Companion.intentToReviewDeckFromShortcuts
3029
import com.ichi2.anki.R
3130
import com.ichi2.anki.analytics.UsageAnalytics
31+
import com.ichi2.anki.common.coroutines.applicationScope
3232
import com.ichi2.anki.common.crashreporting.CrashReportService
3333
import com.ichi2.anki.isCollectionEmpty
3434
import com.ichi2.anki.libanki.DeckId
@@ -104,7 +104,7 @@ class DeckPickerWidget : AnalyticsWidgetProvider() {
104104
showEmptyWidget(context, appWidgetManager, appWidgetId, remoteViews)
105105
return
106106
}
107-
AnkiDroidApp.applicationScope.launch {
107+
applicationScope.launch {
108108
val isCollectionEmpty = isCollectionEmpty()
109109
if (isCollectionEmpty) {
110110
showEmptyCollection(context, appWidgetManager, appWidgetId, remoteViews)

common/android/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ dependencies {
6060

6161
implementation(libs.androidx.annotation)
6262
implementation(libs.jakewharton.timber)
63+
implementation(libs.kotlinx.coroutines.core)
6364

6465
testImplementation(libs.kotlin.test)
6566
testImplementation(libs.junit.jupiter)

0 commit comments

Comments
 (0)