2012-08-12 67 views
0

爲什麼Cursor.getLong()Cursor.getString()可以在模擬器上正常工作,但不是運行相同版本Android的實際設備?光標的getLong()和getString()在模擬器上工作,但不是等效設備

我對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; 
} 

回答

1

遊標的getLong()和GetString()在模擬器上工作,但不等同裝置...我知道,獲取光標至少部分地工作,因爲note.getColumnName(1)工作正常調試器。我也證實getLong()和getString()的參數正確顯示。

遊標的getLong()和getString()方法在模擬器和實際設備上的工作方式相同。

如果你看看你的logcat,你會看到你的問題的原因是,有沒有數據:

android.database.CursorIndexOutOfBoundsException:指數0請求,大小爲0

看來光標是空的,你的表(在設備上)有任何行嗎?


新增自評

我們發現您所做的假設,即所有的行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()返回false

  2. 始終假定光標可能是空的,明白一個空指針不不等於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); 
        } 
    } 
    
+0

是的,有八個保存的註釋(行)。在我嘗試編輯它們之前,它們都會在應用程序加載時正常顯示。 – Pops 2012-08-12 19:57:27

+0

'fetchNote(int i)'的代碼是什麼? – Sam 2012-08-12 19:59:02

+0

我已將它添加到問題中。它與[Android開發人員教程](http://developer.android.com/training/notepad/notepad-ex3.html)中給出的代碼完全相同,除了已更改的變量名稱。 – Pops 2012-08-12 20:03:42

0

這裏的差異是由巧合造成的。當我問這個問題的時候,我從來沒有在模擬器中刪除過筆記。其結果是,我有筆記有1,2,3和4數據庫ID當我問數據庫返回的它包含音符的數量,我成立了一個

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); 
} 
相關問題