2 votes

L'exception dans le flux n'est pas rattrapée

J'ai un flux kotlin dans lequel une exception est levée à mi-chemin. Quoi que je fasse, l'exception n'est pas rattrapée.

Le flux est le suivant : Dans le modèle de vue, j'ai une valeur qui doit être relue à partir d'une base de données lors d'un changement de date. J'utilise pour cela une carte de commutation.

 val branches:LiveData<List<SCBranch>> = currentDay.switchMap {
    schooldataUseCases.getBranches(it)
            .catch{
                 exception ->withContext(Dispatchers.Main) {
                    Timber.d("catching exception in switchmap")
                    uncaughtException.value = exception.message
                }
            }
            .asLiveData

Le cas d'utilisation est le suivant :

override fun getBranches(day:Day): Flow<List<SCBranch>> =
        schooldataRepository.getBranchesForSchoolPeriodFlow(schoolPeriodManager.getSchoolPeriodFor(day.startTime))

Le SchoolPeriodManager sélectionne une période scolaire pour la date demandée. S'il n'y a pas de période scolaire définie pour la date demandée, il lève une exception. Je veux attraper cette exception et informer les utilisateurs qu'ils ont sélectionné une date invalide par le biais d'une autre liveData 'uncaughtexception'.

Hélas, mon application se termine par une exception Fatal qui est en fait l'exception lancée par le schoolPeriodManager. Le bloc catch dans le switchmap n'attrape donc pas l'exception.

J'ai essayé d'ajouter un CoroutineExceptionHandler au flux comme ceci :

val branches:LiveData<List<SCBranch>> = currentDay.switchMap {
    schooldataUseCases.getBranches(it)
            .asLiveData( exceptionHandler)
}

L'exceptionHandler n'attrape pas non plus l'exception. L'application se termine toujours par la même exception fatale

Comment dois-je implémenter le bloc catch pour attraper l'exception soulevée ?

1voto

Pedro Okawa Points 400

J'ai eu le même problème.

Pour gérer la capture, vous devez émettre la valeur, par exemple :

 val branches:LiveData<List<SCBranch>> = currentDay.switchMap {
    schooldataUseCases.getBranches(it)
            .catch { exception ->
                Timber.d("catching exception in switchmap")
                emit(exception.message)
            }
            .asLiveData()

Mais dans votre cas, la valeur émise lors du catch n'est pas la même que celle de la map, donc vous devez peut-être créer une classe enveloppante pour cela, comme une classe scellée avec un contenu pour le succès et l'erreur lors du catch.

    sealed class BranchesState {
        data class Success(val branches: List<Int>) : BranchesState()
        data class Error(val message: String) : BranchesState()
        object Loading : BranchesState()
    }

    val branches: LiveData<BranchesState> = currentDay.switchMap {
        schooldataUseCases.getBranches(it)
            .map { BranchesState.Success(it) as BranchesState }
            .onStart { emit(BranchesState.Loading) }
            .catch { exception ->
                Timber.d("catching exception in switchmap")
                emit(BranchesState.Error(exception.message))
            }
            .asLiveData()

PS : Le cast est nécessaire sur map car sinon il y aura une erreur sur le fait que le liveData que vous essayez d'utiliser est le type de BranchesState.Success au lieu de BranchesState

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X