Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/api/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android ViewModel如何捕获上述层未引发的异常?_Android_Kotlin_Exception_Mvvm - Fatal编程技术网

Android ViewModel如何捕获上述层未引发的异常?

Android ViewModel如何捕获上述层未引发的异常?,android,kotlin,exception,mvvm,Android,Kotlin,Exception,Mvvm,目前正在Kotlin开发Android应用程序,我决定学习MVVM模式 我的处境是: 片段-->视图模型-->控制器-->存储库 我的控制器仅用作当前会话的缓存 目前可以联系我的API,我想处理可能发生的潜在异常,如“UnknownHostException”、“SocketTimeoutException”,并为每个异常显示不同的消息 NB:我使用了改进版2.6.0和协同程序来完成这项工作 请求与API联系的步骤如下: 片段订阅viewModel变量 viewModel启动其“fetchC

目前正在Kotlin开发Android应用程序,我决定学习MVVM模式

我的处境是:

片段-->视图模型-->控制器-->存储库

我的控制器仅用作当前会话的缓存

目前可以联系我的API,我想处理可能发生的潜在异常,如“UnknownHostException”、“SocketTimeoutException”,并为每个异常显示不同的消息

NB:我使用了改进版2.6.0协同程序来完成这项工作

请求与API联系的步骤如下:

  • 片段订阅viewModel变量

  • viewModel启动其“fetchCommandList”方法,在该方法中,它启动一个带有try/catch的协同程序,并要求控制器返回命令列表

  • 如果需要,控制器将调用存储库

  • 存储库尝试在try/catch块中检索数据

这就是我的问题所在。如果您阅读正确,“我的控制器”没有try/catch,但是,如果在存储库中引发异常,viewModel会很好地捕捉到它,并更改其LiveData,从而在片段中显示异常的特定消息

我不明白异常如何能够“跳过”控制器层,并且仍然到达viewModel

以下是从视图到模型的每个图层的代码:

关于错误LiveData的片段部分

对控制器的ViewModel调用

视图模型调用的控制器getCommandsList(无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
    }
}