为什么Cursor.getLong()
和Cursor.getString()
可以在模拟器上正常运行,但不能在运行相同版本Android的实际设备上正常运行?
我对Android Notepad tutorial的第三版进行了一些补充,涉及以编程方式更改笔记的标题。 (我最近在Obtaining the current Android view and forcing it to be redrawn询问了这个项目。)我的更改在我的模拟器中工作正常,但在我的测试手机上导致应用程序结束“很遗憾,程序停止了”。
以下是发生这种情况的方法:
public void expandNoteTitle(int i) {
Cursor note = fetchNote(i);
long rowId =
note.getLong(note.getColumnIndexOrThrow(NotesDbAdapter.KEY_ROWID));
String title =
note.getString(note.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE)) + "W";
String body =
note.getString(note.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY));
updateNote(rowId, title, body);
}
我知道获取光标至少部分有效,因为note.getColumnName(1)
在调试器中工作正常。我还确认getLong()
和getString()
的参数正确显示。
这是LogCat输出:
08-12 15:35:29.735: D/AndroidRuntime(17937): Shutting down VM
08-12 15:35:29.735: W/dalvikvm(17937): threadid=1: thread exiting with uncaught exception (group=0x40a3d1f8)
08-12 15:35:29.751: E/AndroidRuntime(17937): FATAL EXCEPTION: main
08-12 15:35:29.751: E/AndroidRuntime(17937): android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
08-12 15:35:29.751: E/AndroidRuntime(17937): at android.database.AbstractCursor.checkPosition(AbstractCursor.java:400)
08-12 15:35:29.751: E/AndroidRuntime(17937): at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:136)
08-12 15:35:29.751: E/AndroidRuntime(17937): at android.database.AbstractWindowedCursor.getLong(AbstractWindowedCursor.java:74)
08-12 15:35:29.751: E/AndroidRuntime(17937): at notepad.NotesDbAdapter.expandNoteTitle(NotesDbAdapter.java:212)
08-12 15:35:29.751: E/AndroidRuntime(17937): at notepad.NotesDbAdapter.expandNoteTitles(NotesDbAdapter.java:201)
08-12 15:35:29.751: E/AndroidRuntime(17937): at notepad.NotepadMain.expandTitles(NotepadMain.java:167)
08-12 15:35:29.751: E/AndroidRuntime(17937): at notepad.NotepadMain.onMenuItemSelected(NotepadMain.java:115)
08-12 15:35:29.751: E/AndroidRuntime(17937): at com.android.internal.policy.impl.PhoneWindow.onMenuItemSelected(PhoneWindow.java:950)
08-12 15:35:29.751: E/AndroidRuntime(17937): at [SNIPPED FOR LENGTH]
08-12 15:35:29.751: E/AndroidRuntime(17937): at dalvik.system.NativeStart.main(Native Method)
08-12 15:36:49.993: I/Process(17937): Sending signal. PID: 17937 SIG: 9
这是fetchNote()
的代码。除了变量名之外,它与教程中给出的版本相同。
public Cursor fetchNote(long rowId) throws SQLException {
Cursor mCursor = database.query(true, DATABASE_TABLE, new String[] {
KEY_ROWID, KEY_TITLE, KEY_BODY }, KEY_ROWID + "=" + rowId, null,
null, null, null, null);
if(mCursor != null) {
mCursor.moveToFirst();
}
return mCursor;
}
答案 0 :(得分:1)
Cursor的getLong()和getString()在模拟器上工作但不是等效设备...我知道获取光标至少部分有效,因为note.getColumnName(1)在调试器中工作正常。我还确认getLong()和getString()的参数正确显示。
Cursor的getLong()和getString()方法在仿真器和实际设备上的工作方式相同。
如果您查看LogCat,您会发现问题的原因是没有数据:
android.database.CursorIndexOutOfBoundsException:请求索引0,大小为0
看来Cursor为空,你的表(在设备上)是否有任何行?
从评论中添加
正如我们发现你假设你的所有行id都是顺序的,但事实并非如此。以下是我的两个建议,即获取正确的数据,并防止将来的任何力量从你的游标中关闭:
获取所有现有的行ID并迭代它们:
Cursor notes = database.query(DATABASE_TABLE, new String[] { KEY_ROWID }, null, null, null, null, null, null);
while(notes.moveToNext())
expandNoteTitle(notes.getLong(0));
要遍历新的Cursor,只需检查moveToNext()的返回值。当Cursor的索引设置为-1
时(就像它是新的一样),moveToNext()将移动到索引0
并仅在有有效数据时返回true
,否则如果不是rows moveToNext()返回false
。
始终假设Cursor可以为空并且理解空光标不等于null
:
public Cursor fetchNote(long rowId) throws SQLException {
return database.query(true, DATABASE_TABLE,
new String[] { KEY_ROWID, KEY_TITLE, KEY_BODY },
KEY_ROWID + "=" + rowId, null, null, null, null, null);
}
public void expandNoteTitle(long rowId) {
Cursor note = fetchNote(rowId);
if(note.getCount() > 0) {
// You could also use if(cursor.moveToNext()) or if(cursor.moveToFirst()), both of these return true / false depending on whether there is valid data
String title =
note.getString(note.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE)) + "W";
String body =
note.getString(note.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY));
updateNote(rowId, title, body);
}
}
答案 1 :(得分:0)
这里的差异是巧合引起的。当我问这个问题时,我从未在模拟器中删除过注释。结果,我在那里的笔记有数据库ID为1,2,3和4.当我要求数据库返回它包含的笔记数时,我设置了
for(int i = 1; i <= numberOfNotes; i++) { ... }
环。这与现有ID匹配只是因为在创建注释时ID被分配了下一个最高整数。在设备上,我删除了一些注释,因此ID不是一个很好的1对n序列。这是代码的样子:
public void expandNoteTitles() {
Cursor notes = database.query(DATABASE_TABLE, new String[] { KEY_ROWID },
null, null, null, null, null, null);
notes.moveToFirst();
for(int i = 0; i < notes.getCount(); i++) {
expandNoteTitle(notes.getLong(0));
notes.moveToNext();
}
}
public void expandNoteTitle(long rowId) {
Cursor note = fetchNote(rowId);
String title =
note.getString(note.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE)) + "W";
String body =
note.getString(note.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY));
updateNote(rowId, title, body);
}