0

I am trying to come up with an exception handling strategy for my Android application (although this may also apply to any Java app). For example, I am looking at the delete() ContentProvider function in the example Notepad application:

public int delete(Uri uri, String where, String[] whereArgs) {
    SQLiteDatabase db = mOpenHelper.getWritableDatabase();
    int count;
    switch (sUriMatcher.match(uri)) {
        case NOTES:
            count = db.delete(NOTES_TABLE_NAME, where, whereArgs);
            break;

        case NOTE_ID:
            String noteId = uri.getPathSegments().get(1);
            count = db.delete(NOTES_TABLE_NAME, NoteColumns._ID + "=" + noteId
                    + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);
            break;

        default:
            throw new IllegalArgumentException("Unknown URI " + uri);
    }

    getContext().getContentResolver().notifyChange(uri, null);
    return count;
}

What happens if the Uri is null? or getContext()? or getContentresolver()?

I have come to the conclusion that the ContentResolver is not the place to catch the exceptions, but it should re-throw them or throw new exceptions so the app can display a meaningful error message.

Would the following or something similar be a bad approach (overkill) - should I just let NullPointerExceptions, etc. bubble up to the top to be handled in a more generic way (as per the example)?.

public int delete(Uri uri, String where, String[] whereArgs) 
    throws SQLiteException, IllegalArgumentException, NotifyException {

    if (null != mOpenHelper) {
       SQLiteDatabase db = mOpenHelper.getWritableDatabase();
       if (null != db) {
           if (null != uri) {
               int count = 0;
               switch (sUriMatcher.match(uri)) {
                   case NOTES:
                       count = db.delete(NOTES_TABLE_NAME, where, whereArgs);
                       break;

                   case NOTE_ID:
                       String noteId = uri.getPathSegments().get(1);
                       count = db.delete(NOTES_TABLE_NAME, NoteColumns._ID + "=" + noteId
                        + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);
                       break;

                   default:
                       throw new IllegalArgumentException("Unknown URI " + uri);
               }

               if (null != getContext()) && (null != getContentResolver()) {
                   getContext().getContentResolver().notifyChange(uri, null);
               } else {
                   throw NotifyException("Failed to notify change");
               }
               return count;
            } else {
                throw new IllegalArgumentException("Must provide URI");
            }
        } else {
            throw new SQLiteException("Failed to get database");
        }
    } else {
        throw new SQLiteException("Invalid database helper");
    }
}

Disclaimer: this code may not compile! it is an example.

It certainly is harder to read! I don't know what the right balance is and need some help!.

Update: I read through Android's recommended practices (see http://source.android.com/source/code-style.html#java-language-rules) but it just confused me further!

4

2 回答 2

1

有不同的方法可以解决这个问题。我非常喜欢“清洁代码”这本书。

您可以使用一个简单的 try catch 块来捕获一般异常。在这个 catch 块中,您可以运行自己编写的失败方法 systemOutFailure(Uri, Context, ContentResolver)。此方法检查失败并抛出正确的异常。无论如何,我认为 getContext 永远不能为空。您还可以更进一步,不要使用失败方法,而是使用自己的失败类来处理异常并抛出正确的异常。

throws 的问题是你必须“把它翻过来”,所以它不是很好的 OO 设计——如果你必须对另一个异常进行更改或扩展,则 throws 是非常静态的。

于 2012-11-15T20:18:56.753 回答
1

处理异常的想法是清楚地表明发生错误的原因,并可能根据错误执行一些操作。所以,请考虑:

  1. 定义自己的从 Java 异常派生的异常类

  2. 将您的代码放在 try/catch 块中。当您捕获异常时,您会使用跟踪记录它,然后抛出您自己的异常并给出明确的解释。

  3. 在某些时候,您会捕获自己的异常,提取信息并将信息显示在屏幕上或发送回程序用户(如果您提供 Web 服务)

代码示例:

public class MyException extends Exception {

public static final String MYSeparator = "!@#!";
public MyException() {
    super();
}

public MyException(String message) {
    super(message);
}

public MyException(Throwable cause) {
    super(cause);
}

public MyException(String message, Throwable cause) {
    super(message, cause);
}

public MyException(String errorCode, String errorDescription,
        Throwable cause) {
    super(errorCode + MYSeparator + errorDescription, cause);
}

public MyException(String errorCode, String errorDescription) {
    super(errorCode + MYSeparator + errorDescription);
}

}

于 2012-11-15T20:27:58.697 回答