Tai*_*han 2 rest android kotlin kotlin-flow
我在流程内发出异常并得到以下异常。
IllegalStateException: Flow exception transparency is violated:
Previous 'emit' call has thrown exception java.lang.NullPointerException, but then emission attempt of value 'planetbeyond.domain.api.Resource$Error@85b4d28' has been detected.
Emissions from 'catch' blocks are prohibited in order to avoid unspecified behaviour, 'Flow.catch' operator can be used instead.
For a more detailed explanation, please refer to Flow documentation.
at kotlinx.coroutines.flow.internal.SafeCollector.exceptionTransparencyViolated(SafeCollector.kt:140)
at kotlinx.coroutines.flow.internal.SafeCollector.checkContext(SafeCollector.kt:104)
at kotlinx.coroutines.flow.internal.SafeCollector.emit(SafeCollector.kt:83)
at kotlinx.coroutines.flow.internal.SafeCollector.emit(SafeCollector.kt:66)
at planetbeyond.domain.use_cases.OptionSelectedCountUsecase$invoke$1.invokeSuspend(OptionSelectedCountUsecase.kt:20)
Run Code Online (Sandbox Code Playgroud)
OptionSelectedCountUsecase.kt
class OptionSelectedCountUsecase @Inject constructor(
private val repository: Repository
) {
operator fun invoke(questionId: Int): Flow<Resource<List<OptionSelectedCountModel>>> = flow {
emit(Resource.Loading())
try {
val data = repository.getOptionSelectedCount(questionId)
emit(Resource.Success(data))
} catch (e: Exception) {
emit(Resource.Error(e.toString()))// crashed at this line when api don't response anything or some sort of server error
}
}
}
Run Code Online (Sandbox Code Playgroud)
存储库.kt
interface Repository{
suspend fun getOptionSelectedCount(questionId: Int):List<OptionSelectedCountModel>
}
Run Code Online (Sandbox Code Playgroud)
RepositoryImpl.kt
class RepositoryImpl @Inject constructor(
private val apiService: ApiService
) : Repository {
override suspend fun getOptionSelectedCount(questionId: Int): List<OptionSelectedCountModel> {
return apiService.getOptionSelectedCount(questionId).data.map {
it.toModel()
}
}
}
Run Code Online (Sandbox Code Playgroud)
ApiService.kt
interface ApiService {
@GET("get_option_selected_count")
suspend fun getOptionSelectedCount(
@Query("question_id") question_id: Int
): WebResponse<List<OptionSelectedCountDto>>
}
Run Code Online (Sandbox Code Playgroud)
LiveShowQuestionViewModel.kt
@HiltViewModel
class LiveShowQuestionsViewModel @Inject constructor(
private val optionSelectedCountUsecase: OptionSelectedCountUsecase
) : ViewModel() {
fun getOptionSelectedCount(questionId: Int) {
optionSelectedCountUsecase(questionId).onEach {
when (it) {
is Resource.Loading -> {
_optionSelectedCountState.value = OptionSelectedCountState(isLoading = true)
}
is Resource.Error -> {
_optionSelectedCountState.value = OptionSelectedCountState(error = it.message)
}
is Resource.Success -> {
_optionSelectedCountState.value = OptionSelectedCountState(data = it.data)
}
}
}///.catch { } // Why must I have to handle it here
.launchIn(viewModelScope)
}
}
Run Code Online (Sandbox Code Playgroud)
是否有必要像上面评论的那样处理流程外的异常。最好的做法是什么。
问题是您包装了一个emit调用try并尝试在匹配的块中发出catch。这意味着如果emit调用本身抛出(这可能是由流程的某些下游问题引起的),它将指示再次发出。这是非常暧昧和脆弱的行为。
相反,您可以将发出调用移到 try/catch 之外:
class OptionSelectedCountUsecase @Inject constructor(
private val repository: Repository
) {
operator fun invoke(questionId: Int): Flow<Resource<List<OptionSelectedCountModel>>> = flow {
emit(Resource.Loading())
val result = try {
val data = repository.getOptionSelectedCount(questionId)
Resource.Success(data)
} catch (e: Exception) {
Resource.Error(e.toString())
}
emit(result)
}
}
Run Code Online (Sandbox Code Playgroud)
不知何故,您在收集器中导致了 NullPointerException。这是一个需要解决的单独问题。
| 归档时间: |
|
| 查看次数: |
6099 次 |
| 最近记录: |