【问题标题】:Cursor's getLong() and getString() work on an emulator but not an equivalent deviceCursor 的 getLong() 和 getString() 可以在模拟器上工作,但不能在等效设备上工作
【发布时间】:2012-08-14 01:31:16
【问题描述】:

为什么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;
}

【问题讨论】:

    标签: android android-emulator


    【解决方案1】:

    Cursor 的 getLong() 和 getString() 在模拟器上工作,但不是在等效设备上工作...我知道获取光标至少部分工作,因为 note.getColumnName(1) 在调试器中工作正常。我还确认 getLong() 和 getString() 的参数正确显示。

    Cursor 的 getLong() 和 getString() 方法在模拟器和实际设备上的工作方式相同。

    如果您查看您的 LogCat,您会发现问题的原因是没有数据:

    android.database.CursorIndexOutOfBoundsException: 请求索引 0,大小为 0

    光标好像是空的,你的表(在设备上)有行吗?


    从 cmets 添加

    我们发现您假设您的所有行 ID 都是连续的,但事实并非如此。以下是我获取正确数据并防止任何未来强制关闭光标的两个建议:

    1. 获取所有现有的行 ID 并遍历它们:

      Cursor notes = database.query(DATABASE_TABLE, new String[] { KEY_ROWID }, null, null, null, null, null, null);
      
      while(notes.moveToNext()) 
          expandNoteTitle(notes.getLong(0)); 
      

      要遍历一个新的游标,您只需检查 moveToNext() 的返回值。当光标的索引设置为-1 时(就像它是新的一样),moveToNext() 将移动到索引0 并仅在有有效数据时返回true,否则如果没有行 moveToNext() 返回@ 987654326@.

    2. 始终假设 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);
          }
      }
      

    【讨论】:

    • 是的,有八个已保存的笔记(行)。在我尝试编辑它们之前,它们都会在应用加载时正常显示。
    • 我已将其添加到问题中。它与the Android Developers tutorial 中给出的代码完全相同,只是变量名有所改变。
    • 好的,看起来不错。所以 id (int i) 并不是指实际的行。这个 id 是从哪里来的?
    • 我正在向数据库询问其所有行的列表,获取其大小,然后遍历每一行。
    • 你的评论给了我一个新的想法。我认为我从未从模拟器中的表中删除任何行。我刚刚这样做了,现在它也崩溃了。我现在认为 ID 是数据库中的主键,我不能只从 ID 1 单步到 ID number-of-rows。
    【解决方案2】:

    这里的差异是巧合造成的。在我问这个问题时,我从未在模拟器中删除过笔记。结果,我那里的笔记的数据库 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);
    }
    

    【讨论】:

      猜你喜欢
      • 2017-06-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-19
      • 2023-03-23
      • 1970-01-01
      • 1970-01-01
      • 2013-07-02
      相关资源
      最近更新 更多