From c7ea8ec2b2824fd390c2d4689edc52f1d36b6047 Mon Sep 17 00:00:00 2001 From: Matthias Urhahn <matthias.urhahn@sap.com> Date: Fri, 13 Nov 2020 19:35:28 +0100 Subject: [PATCH] Improve cancelation exception handling (DEV) (#1591) * Catch cancellation exceptions for coroutines launched on the viewModelScope. * Use the viewmodel provided launch method to use common handling. Co-authored-by: harambasicluka <64483219+harambasicluka@users.noreply.github.com> Co-authored-by: chris-cwa <69595386+chris-cwa@users.noreply.github.com> --- .../test/crash.ui/SettingsCrashReportViewModel.kt | 5 +---- .../debugoptions/ui/DebugOptionsFragmentViewModel.kt | 5 +---- .../ui/TestRiskLevelCalculationFragmentCWAViewModel.kt | 10 ++++------ .../onboarding/OnboardingTracingFragmentViewModel.kt | 4 +--- .../rki/coronawarnapp/util/viewmodel/CWAViewModel.kt | 10 ++++++++-- 5 files changed, 15 insertions(+), 19 deletions(-) diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/crash.ui/SettingsCrashReportViewModel.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/crash.ui/SettingsCrashReportViewModel.kt index 234022907..44d3e0cd0 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/crash.ui/SettingsCrashReportViewModel.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/crash.ui/SettingsCrashReportViewModel.kt @@ -4,7 +4,6 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.asLiveData import androidx.lifecycle.map -import androidx.lifecycle.viewModelScope import com.squareup.inject.assisted.AssistedInject import de.rki.coronawarnapp.bugreporting.event.BugEvent import de.rki.coronawarnapp.bugreporting.reportProblem @@ -12,9 +11,7 @@ import de.rki.coronawarnapp.bugreporting.storage.repository.BugRepository import de.rki.coronawarnapp.util.viewmodel.CWAViewModel import de.rki.coronawarnapp.util.viewmodel.SimpleCWAViewModelFactory import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch import timber.log.Timber -import java.lang.Exception class SettingsCrashReportViewModel @AssistedInject constructor( private val crashReportRepository: BugRepository @@ -28,7 +25,7 @@ class SettingsCrashReportViewModel @AssistedInject constructor( createBugEventFormattedText(it) } - fun deleteAllCrashReports() = viewModelScope.launch(Dispatchers.IO) { + fun deleteAllCrashReports() = launch(Dispatchers.IO) { crashReportRepository.clear() } diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/debugoptions/ui/DebugOptionsFragmentViewModel.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/debugoptions/ui/DebugOptionsFragmentViewModel.kt index c58e64556..dd0542685 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/debugoptions/ui/DebugOptionsFragmentViewModel.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/debugoptions/ui/DebugOptionsFragmentViewModel.kt @@ -1,7 +1,6 @@ package de.rki.coronawarnapp.test.debugoptions.ui import android.content.Context -import androidx.lifecycle.viewModelScope import com.squareup.inject.assisted.AssistedInject import de.rki.coronawarnapp.environment.EnvironmentSetup import de.rki.coronawarnapp.environment.EnvironmentSetup.Type.Companion.toEnvironmentType @@ -19,8 +18,6 @@ import de.rki.coronawarnapp.util.ui.SingleLiveEvent import de.rki.coronawarnapp.util.ui.smartLiveData import de.rki.coronawarnapp.util.viewmodel.CWAViewModel import de.rki.coronawarnapp.util.viewmodel.SimpleCWAViewModelFactory -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch import java.io.File class DebugOptionsFragmentViewModel @AssistedInject constructor( @@ -79,7 +76,7 @@ class DebugOptionsFragmentViewModel @AssistedInject constructor( fun shareLogFile() { CWADebug.fileLogger?.let { - viewModelScope.launch(context = Dispatchers.Default) { + launch { if (!it.logFile.exists()) return@launch val externalPath = File( diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt index d0a85e7f0..765ac237e 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt @@ -4,7 +4,6 @@ import android.content.Context import androidx.lifecycle.MutableLiveData import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.asLiveData -import androidx.lifecycle.viewModelScope import com.google.android.gms.nearby.exposurenotification.ExposureInformation import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject @@ -37,7 +36,6 @@ import de.rki.coronawarnapp.util.viewmodel.CWAViewModel import de.rki.coronawarnapp.util.viewmodel.CWAViewModelFactory import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.sample -import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import timber.log.Timber import java.io.File @@ -90,7 +88,7 @@ class TestRiskLevelCalculationFragmentCWAViewModel @AssistedInject constructor( } fun resetRiskLevel() { - viewModelScope.launch { + launch { withContext(Dispatchers.IO) { try { // Preference reset @@ -122,7 +120,7 @@ class TestRiskLevelCalculationFragmentCWAViewModel @AssistedInject constructor( ) fun startENFObserver() { - viewModelScope.launch { + launch { try { var workState = riskScoreState.value!! @@ -263,7 +261,7 @@ class TestRiskLevelCalculationFragmentCWAViewModel @AssistedInject constructor( dir.mkdirs() var googleFileList: List<File> - viewModelScope.launch { + launch { googleFileList = KeyFileHelper.asyncCreateExportFiles(appleFiles, dir) Timber.i("Provide ${googleFileList.count()} files with ${appleKeyList.size} keys with token $token") @@ -291,7 +289,7 @@ class TestRiskLevelCalculationFragmentCWAViewModel @AssistedInject constructor( } fun clearKeyCache() { - viewModelScope.launch { keyCacheRepository.clear() } + launch { keyCacheRepository.clear() } } @AssistedInject.Factory diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingTracingFragmentViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingTracingFragmentViewModel.kt index 9d996c01e..a710675c0 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingTracingFragmentViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingTracingFragmentViewModel.kt @@ -1,6 +1,5 @@ package de.rki.coronawarnapp.ui.onboarding -import androidx.lifecycle.viewModelScope import com.squareup.inject.assisted.AssistedInject import de.rki.coronawarnapp.exception.ExceptionCategory import de.rki.coronawarnapp.exception.reporting.report @@ -10,7 +9,6 @@ import de.rki.coronawarnapp.storage.interoperability.InteroperabilityRepository import de.rki.coronawarnapp.ui.SingleLiveEvent import de.rki.coronawarnapp.util.viewmodel.CWAViewModel import de.rki.coronawarnapp.util.viewmodel.SimpleCWAViewModelFactory -import kotlinx.coroutines.launch class OnboardingTracingFragmentViewModel @AssistedInject constructor( private val interoperabilityRepository: InteroperabilityRepository @@ -25,7 +23,7 @@ class OnboardingTracingFragmentViewModel @AssistedInject constructor( // Reset tracing state in onboarding fun resetTracing() { - viewModelScope.launch { + launch { try { if (InternalExposureNotificationClient.asyncIsEnabled()) { InternalExposureNotificationClient.asyncStop() diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/viewmodel/CWAViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/viewmodel/CWAViewModel.kt index 9f3eddff2..40cd6f768 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/viewmodel/CWAViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/viewmodel/CWAViewModel.kt @@ -5,8 +5,8 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import de.rki.coronawarnapp.util.coroutine.DefaultDispatcherProvider import de.rki.coronawarnapp.util.coroutine.DispatcherProvider +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Job import kotlinx.coroutines.launch import timber.log.Timber import kotlin.coroutines.CoroutineContext @@ -29,7 +29,13 @@ abstract class CWAViewModel constructor( fun launch( context: CoroutineContext = dispatcherProvider.Default, block: suspend CoroutineScope.() -> Unit - ): Job = viewModelScope.launch(context = context, block = block) + ) { + try { + viewModelScope.launch(context = context, block = block) + } catch (e: CancellationException) { + Timber.w(e, "launch()ed coroutine was canceled.") + } + } @CallSuper override fun onCleared() { -- GitLab