Android ViewModel如何捕获上述层未引发的异常?
目前正在Kotlin开发Android应用程序,我决定学习MVVM模式 我的处境是: 片段-->视图模型-->控制器-->存储库 我的控制器仅用作当前会话的缓存 目前可以联系我的API,我想处理可能发生的潜在异常,如“UnknownHostException”、“SocketTimeoutException”,并为每个异常显示不同的消息 NB:我使用了改进版2.6.0和协同程序来完成这项工作 请求与API联系的步骤如下:Android ViewModel如何捕获上述层未引发的异常?,android,kotlin,exception,mvvm,Android,Kotlin,Exception,Mvvm,目前正在Kotlin开发Android应用程序,我决定学习MVVM模式 我的处境是: 片段-->视图模型-->控制器-->存储库 我的控制器仅用作当前会话的缓存 目前可以联系我的API,我想处理可能发生的潜在异常,如“UnknownHostException”、“SocketTimeoutException”,并为每个异常显示不同的消息 NB:我使用了改进版2.6.0和协同程序来完成这项工作 请求与API联系的步骤如下: 片段订阅viewModel变量 viewModel启动其“fetchC
- 片段订阅viewModel变量
- viewModel启动其“fetchCommandList”方法,在该方法中,它启动一个带有try/catch的协同程序,并要求控制器返回命令列表
- 如果需要,控制器将调用存储库
- 存储库尝试在try/catch块中检索数据
覆盖getCommandsList():列表{
如果(m_commandList.size,则挂起的函数自然会将运行时异常传播给顶级调用方,直到它到达try-and-catch块或协同路由作用域,然后由exceptionHandler处理或导致应用程序崩溃
因此,在您的情况下,没有什么可疑的,并且没有必要在存储库层中重试try&catch with exception
请参阅协同程序异常处理在存储库中设置try-catch,然后在catch中设置try-catch,并设置Trow e
,这有什么意义?我想传播异常,直到viewModel处理其中的UI显示。存储库只需将异常提供给较低层那么try-catch有什么作用呢如果它捕获异常并抛出相同的东西?那么你的try-catch是冗余的。我想我不知道异常是如何工作的,对我来说,如果我没有在我的存储库中这样做,异常就会丢失。好吧,你可以测试它。编写一个函数来抛出一个异常,其中包含一个类似于你的try-catch,然后是一个没有try-catch的异常,看看它们是否是different或sameSo,如果我理解得很好(对不起,我不是英国人),异常将“自动”抛出,直到顶级调用方(这里是我的ViewModel)?因此我可以删除我的存储库中的try catch,但让ViewModel中的一个?是的,并检查Coroutines文档中的异常处理,我在注释中添加了它谢谢您的帮助!!
mviewModel.mErrorStatus.observe(viewLifecycleOwner, Observer {
mbinding.fragmentCommandListRecyclerview.visibility = if (it != null) View.GONE else View.VISIBLE
mbinding.fragmentCommandListErrorTextView.visibility = if (it != null) View.VISIBLE else View.GONE
mbinding.fragmentCommandListErrorTextView.text = it
})
fun fetchCommandList(){
//TODO : contact the controller method tha will firstly check is in list & if not result ask the repository to retrieve it
viewModelScope.launch {
mProgressBar.postValue(true)
try {
mCommandList.postValue(CommandControllerMock.getCommandsList())
mCommandActive.postValue(CommandControllerMock.getCurrentCommand())
}
catch (e: UnknownHostException) {
//this exception occurs when there is no internet connection or host is not available
//so inform user that something went wrong
mErrorStatus.postValue(e.message)
} catch (e: SocketTimeoutException) {
//this exception occurs when time out will happen
//so inform user that something went wrong
mErrorStatus.postValue(e.message)
} catch (e: Exception) {
//this is generic exception handling
//so inform user that something went wrong
mErrorStatus.postValue(e.message)
}
finally {
mProgressBar.postValue(false)
}
}
}
override suspend fun getCommandsList(): List<Command> {
if(m_commandList.size <= 0){
//Todo: replace by auth.userID
//Todo : before return the result, check if a command is already active to set currentCommand
val returnedList = m_commandRepository.getAllCommandByUser(USER_ID)
returnedList?.let{
m_commandList = it.toMutableList()
}
checkForActiveCommand()
}
return m_commandList
}
override suspend fun getAllCommandByUser(idUser: String): List<Command>? {
try {
val response = apiService.getAllCommandByUser(idUser)
if (response.isSuccessful) {
return response.body()
} else {
throw Exception("not 200 code")
}
} catch (e: Exception) {
//this is generic exception handling
//so inform user that something went wrong
throw e
}
}