【问题标题】:Exception in flow is not caught未捕获流中的异常
【发布时间】:2023-03-26 02:55:01
【问题描述】:

我有一个 kotlin 流程,其中中途抛出异常。无论我做什么,异常都不会被捕获。

流程是这样的: 在视图模型中,我有值需要在日期更改时从数据库中重新读取。我为此使用了 switchmap。

 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

用例如下:

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

schoolPeriodManager 为请求的日期选择一个 schoolPeriod。如果没有为请求的日期定义 schoolPeriod,则会引发异常。我想捕获该异常并通过另一个 liveData 'uncaughtexception' 通知用户他们选择了无效日期。

唉,我的应用程序以致命异常结束,这确实是 schoolPeriodManager 抛出的异常。所以switchmap中的catch块并没有捕捉到异常。

我尝试向流程中添加一个 CoroutineExceptionHandler,如下所示:

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

exceptionHandler 也不捕获异常。该应用程序仍然以相同的致命异常结束

我应该如何实现 catch 块来捕获引发的异常?

【问题讨论】:

    标签: android kotlin exception flow


    【解决方案1】:

    我也有同样的问题,伙计。

    为了处理catch,你必须发出值,例如:

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

    但在您的情况下,catch 上发出的值与地图中发出的值不同,因此您可能需要为此创建一个包装类,例如带有成功内容和 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:地图上需要强制转换,否则会显示错误,即您尝试使用的 liveData 类型是 BranchesState.Success 而不是 BranchesState

    【讨论】:

    • 不幸的是,这不起作用。可能与抛出异常的方式有关。
    猜你喜欢
    • 1970-01-01
    • 2010-09-28
    • 2012-05-31
    • 1970-01-01
    相关资源
    最近更新 更多