Android 如何处理数据库异常:软件设计

Android 如何处理数据库异常:软件设计,android,exception-handling,software-design,Android,Exception Handling,Software Design,我正在开发一个Android 3.1及以上版本的应用程序,但这个问题并不是针对特定环境的 我有三层:活动(表示)、模型(表示数据库表的对象)和数据(访问SQLite数据库的类) 我所有的数据库方法都是这样的: public void insertUserAnswers(ArrayList<UserAnswer> answers) { try { if ((db == null) || (!db.isOpen())) this.o

我正在开发一个Android 3.1及以上版本的应用程序,但这个问题并不是针对特定环境的

我有三层:活动(表示)、模型(表示数据库表的对象)和数据(访问SQLite数据库的类)

我所有的数据库方法都是这样的:

public void insertUserAnswers(ArrayList<UserAnswer> answers)
{
    try
    {
        if ((db == null) || (!db.isOpen()))
            this.open();
    }
    catch (Exception e) {
        e.printStackTrace();
    }
    finally
    {
        this.close();
    }
}
public void插入应答(数组列表应答)
{
尝试
{
如果((db==null)| |(!db.isOpen()))
这个.open();
}
捕获(例外e){
e、 printStackTrace();
}
最后
{
这个。关闭();
}
}
正如你所看到的,我捕捉到了每一个异常,我不会通知任何人,因为(这是我的问题)我不知道如何去做

如何通知sql命令出错?有什么模式可以做到这一点吗


我想我可以返回一个值来指示这一点,也可以不缓存异常。

对,很抱歉,我没有正确阅读您的问题,因此更改了我的答案


这实际上取决于您预期的异常类型,我看到您取消了所有异常,但您应该能够将其缩小到特定的异常,您可以让调用方处理异常,然后您可以展示祝酒词或其他东西,如果异常是可恢复的,则可以帮助用户解决问题。

一般来说,如果您打算对错误执行操作,或允许其他对象对其执行操作(优雅降级等),则它似乎已纠正以返回适当的返回值。然后,
insertUserAnswers
方法可以返回一个数值,例如指示:

0: "Success"
1: "IO error (file system not accessible or so)"
2: "SQL error (invalid insert query, invalid arguments, ...)"
这可能需要您捕获比基本
异常
更具体的异常,以确定出了什么问题

另外:作为一个用户,我不关心错误的技术细节。我甚至不确定我是否对是否有错误感兴趣。因此,如果你问我,显示错误对话框不一定是“对错误采取行动”。如果这是您唯一想要做的事情(显示错误对话框),那么我建议您不要为返回值而烦恼,完全跳过错误通知


您应该始终以某种方式记录错误(可以通过
log.e(“MyTag”、“My log message”)
或您自己的日志基础结构,如果您愿意的话)。

首先,不要捕获所有这样的异常,很难知道发生了什么错误,也很难准确地通知用户出了什么错误。相反,你可以这样做:

try {
    operationThatThrowsMultipleExceptions();
}
catch (ExceptionTypeOne e){
    // do something here
}
catch (ExceptionTypeTwo e){
    // do something here
}
catch (Exception e){
    // do something here
}
您可以看到,我们在末尾捕获了
异常
,有点像捕获所有类型的内容,以确保我们没有遗漏任何内容

就您的模型而言,我这样做的方式是确保所有数据层对象将其异常抛出到表示层(活动),以便活动能够处理它。在表示层,您可以选择如何向用户显示错误:通常是在一条漂亮、信息丰富的错误消息中。但情况可能并非总是如此。例如,如果您正在填充模型,并且因为数据库没有返回而命中空指针,那么在数据层发现问题,只是不填充模型。然后,当您的表示层显示模型时,将不会有任何内容,这就是您的表示层可以决定如何将其传达给用户的点


总而言之:除非确实有必要,否则不要捕获数据层中的异常。

您可能需要查看
SQLiteOpenHelper
来为您打开数据库(一次或很少)。如果希望多个进程或应用程序能够访问数据,请与
ContentProvider
结合使用

然后确保你的代码不会产生错误(在SQLite级别等),如果你忘记了什么,就让应用程序崩溃——这是知道你做错了什么的最安全的方法,也允许你通过Play/Market报告错误

只有在某些情况下(如文件I/O),您希望代码会产生错误,并且您知道如何处理它们时,捕获异常才是好的

捕获所有内容只会隐藏您的错误并使其难以检测(用户必须不断监视日志消息等等)。如果你的应用程序没有崩溃,但也不可用,因为运行它需要数据库,那么你可能会让用户感到困惑,而不仅仅是让它崩溃

只需将消息打印到logcat即可使用

catch (Exception e) {
    // either 
    Log.w("TAG", e);
    // or
    Log.e("TAG", "some message", e);
}

这将使用您可以选择的标记/日志级别打印消息,而不是使用
W/System.err

谢谢您的回答。我有一个具体的问题,我不知道如何处理:我连接到一个web服务,检索一些数据,然后我将存储在本地。如果此数据已损坏,将导致异常。这不是软件问题,我该如何处理?谢谢。如果数据可能损坏(=您预期的错误不是由错误代码引起的),请捕获相应的异常(不是全部),并找到处理该情况的方法。例如,检查您检索到的数据是否有效,如果没有重试(可能会阻止您以这种方式获得的异常)。如果无法进行自动错误处理,则通知用户,如果可能,可以稍后重试。let it crash方法只适用于您应该修复的错误代码,而不适用于网络超时/传输错误等必须由您的代码处理的事情。