2014-01-23 35 views
0

我在查詢聯繫人電話號碼和姓名。由於這種方法是寫的,我很確定它會給我一個每個電話號碼的新名稱/號碼條目。我會擔心下一個聯繫人列表號碼後,我得到它的工作是,是......Android聯繫人查詢 - 遊標索引超出範圍

我得到一個遊標索引出界失誤上線160,但不知道爲什麼(依然與聯繫人的蠻勁)。我粘貼了彈出錯誤的方法以及logcat。

請幫我找出這個錯誤。另外,如果您知道更有效的查詢方式,我將不勝感激。

在此先感謝

編輯:

由於格雷厄姆Borland的,我看到我的簡單的錯誤是位置 「使用MoveToNext()」。將它移動到for循環的末尾可以修復崩潰。我是對的,它爲每個電話號碼創建一個新條目。但我有3個號碼的聯繫,所以它提供了3個條目,現在我可以使用,但它在每個條目中給出了相同的號碼。有任何想法嗎?

private void getContacts() { 

    String name, number, label; 

    uri = CommonDataKinds.Phone.CONTENT_URI; 
    projection = new String[] { CommonDataKinds.Phone.DISPLAY_NAME, 
      CommonDataKinds.Phone.NUMBER, CommonDataKinds.Phone.LABEL }; 
    selection = null; 
    selectionArgs = null; 
    sortOrder = CommonDataKinds.Phone.DISPLAY_NAME; 

    Cursor peopleCursor = getContentResolver().query(uri, projection, 
      selection, selectionArgs, sortOrder); 

    if (peopleCursor != null) { 

     int indexName = peopleCursor 
       .getColumnIndex(CommonDataKinds.Phone.DISPLAY_NAME); 
     int indexNumber = peopleCursor 
       .getColumnIndex(CommonDataKinds.Phone.NUMBER); 
     int indexLabel = peopleCursor 
       .getColumnIndex(CommonDataKinds.Phone.LABEL); 

     peopleCursor.moveToFirst(); 

     for (int i = 0; i < peopleCursor.getCount(); i++) { 

      ContactNameItems nameItems = new ContactNameItems(); 
      ContactPhoneItems phoneItems = new ContactPhoneItems(); 
      numberList = new ArrayList<ContactPhoneItems>(); 

      peopleCursor.moveToNext(); 

      name = peopleCursor.getString(indexName); // This is line 160 
      number = peopleCursor.getString(indexNumber); 
      label = peopleCursor.getString(indexLabel); 

      if (name != null && !name.isEmpty()) { 

       nameItems.setName(name); 
       mListDataHeader.add(nameItems); 

       if (number != null && !number.isEmpty()) { 

        phoneItems.setNumber(number); 
        phoneItems.setPhoneType(label); 

        numberList.add(phoneItems); 

        mListDataChild.put(mListDataHeader.get(i).getName(), 
          numberList); 
        mListAdapter.notifyDataSetChanged(); 

       } 
      } 
     } 
    } 
    peopleCursor.close(); 
} 



01-22 21:42:21.347: E/AndroidRuntime(793): FATAL EXCEPTION: main 
01-22 21:42:21.347: E/AndroidRuntime(793): java.lang.RuntimeException: Unable to resume activity {com.psesto.expandablelistview/com.psesto.expandablelistview.MainActivity}: android.database.CursorIndexOutOfBoundsException: Index 5 requested, with a size of 5 
01-22 21:42:21.347: E/AndroidRuntime(793): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2742) 
01-22 21:42:21.347: E/AndroidRuntime(793): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2771) 
01-22 21:42:21.347: E/AndroidRuntime(793): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2235) 
01-22 21:42:21.347: E/AndroidRuntime(793): at android.app.ActivityThread.access$600(ActivityThread.java:141) 
01-22 21:42:21.347: E/AndroidRuntime(793): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234) 
01-22 21:42:21.347: E/AndroidRuntime(793): at android.os.Handler.dispatchMessage(Handler.java:99) 
01-22 21:42:21.347: E/AndroidRuntime(793): at android.os.Looper.loop(Looper.java:137) 
01-22 21:42:21.347: E/AndroidRuntime(793): at android.app.ActivityThread.main(ActivityThread.java:5041) 
01-22 21:42:21.347: E/AndroidRuntime(793): at java.lang.reflect.Method.invokeNative(Native Method) 
01-22 21:42:21.347: E/AndroidRuntime(793): at java.lang.reflect.Method.invoke(Method.java:511) 
01-22 21:42:21.347: E/AndroidRuntime(793): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) 
01-22 21:42:21.347: E/AndroidRuntime(793): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) 
01-22 21:42:21.347: E/AndroidRuntime(793): at dalvik.system.NativeStart.main(Native Method) 
01-22 21:42:21.347: E/AndroidRuntime(793): Caused by: android.database.CursorIndexOutOfBoundsException: Index 5 requested, with a size of 5 
01-22 21:42:21.347: E/AndroidRuntime(793): at android.database.AbstractCursor.checkPosition(AbstractCursor.java:424) 
01-22 21:42:21.347: E/AndroidRuntime(793): at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:136) 
01-22 21:42:21.347: E/AndroidRuntime(793): at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:50) 
01-22 21:42:21.347: E/AndroidRuntime(793): at android.database.CursorWrapper.getString(CursorWrapper.java:114) 
01-22 21:42:21.347: E/AndroidRuntime(793): at com.psesto.expandablelistview.MainActivity.getContacts(MainActivity.java:160) 
01-22 21:42:21.347: E/AndroidRuntime(793): at com.psesto.expandablelistview.MainActivity.onResume(MainActivity.java:58) 
01-22 21:42:21.347: E/AndroidRuntime(793): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1185) 
01-22 21:42:21.347: E/AndroidRuntime(793): at android.app.Activity.performResume(Activity.java:5182) 
01-22 21:42:21.347: E/AndroidRuntime(793): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2732) 
01-22 21:42:21.347: E/AndroidRuntime(793): ... 12 more 

的修復:

私人無效getContacts(){

String name, number, label; 

uri = CommonDataKinds.Phone.CONTENT_URI; 
projection = new String[] { CommonDataKinds.Phone.DISPLAY_NAME, 
     CommonDataKinds.Phone.NUMBER, CommonDataKinds.Phone.LABEL }; 
selection = null; 
selectionArgs = null; 
sortOrder = CommonDataKinds.Phone.DISPLAY_NAME; 

Cursor peopleCursor = getContentResolver().query(uri, projection, 
     selection, selectionArgs, sortOrder); 

if (peopleCursor != null) { 

    int indexName = peopleCursor 
      .getColumnIndex(CommonDataKinds.Phone.DISPLAY_NAME); 
    int indexNumber = peopleCursor 
      .getColumnIndex(CommonDataKinds.Phone.NUMBER); 
    int indexLabel = peopleCursor 
      .getColumnIndex(CommonDataKinds.Phone.LABEL); 

    peopleCursor.moveToFirst(); 

    for (int i = 0; i < peopleCursor.getCount(); i++) { 

     ContactNameItems nameItems = new ContactNameItems(); 
     ContactPhoneItems phoneItems = new ContactPhoneItems(); 
     numberList = new ArrayList<ContactPhoneItems>(); 

     name = peopleCursor.getString(indexName); // This is line 160 
     number = peopleCursor.getString(indexNumber); 
     label = peopleCursor.getString(indexLabel); 

     if (name != null && !name.isEmpty()) { 

      nameItems.setName(name); 
      mListDataHeader.add(nameItems); 

      if (number != null && !number.isEmpty()) { 

       phoneItems.setNumber(number); 
       phoneItems.setPhoneType(label); 

       numberList.add(phoneItems); 

       mListDataChild.put(mListDataHeader.get(i).getName(), 
         numberList); 
       mListAdapter.notifyDataSetChanged(); 

      } 
     } 

     peopleCursor.moveToNext(); 
    } 
} 
peopleCursor.close(); 

}

回答

0
peopleCursor.moveToFirst(); 

for (int i = 0; i < peopleCursor.getCount(); i++) { 

    // do some setup 
    peopleCursor.moveToNext(); 
    // read data from the cursor 

這是一個非常複雜的,錯誤的,通過遊標迭代的方式。當您第一次讀取數據時,您已經進入第二行(moveToFirst(),然後是moveToNext())。通過循環的第5次迭代,您已經超過了導致錯誤的結果的結尾。

使用簡單while環代替。

while (peopleCursor.moveToNext()) { 
    .... 
} 

有關更多說明,請參閱What's the best way to iterate an Android Cursor?

+0

我需要添加一個數組列表的值,這就是爲什麼我使用for(如果你知道如何做'同時',我都是耳朵)。但我明白你對'moveToNext'的定位。我將把它移到循環結尾,看看會發生什麼 – Psest328

+0

好的...將它移動到最後修復崩潰(Yay!)。我說得對,它爲每個電話號碼創建了一個新條目。但我有3個號碼的聯繫,所以它提供了3個條目,現在我可以使用,但它在每個條目中給出了相同的號碼。有任何想法嗎? – Psest328

+0

@WizardKnight這是一個不同的故事。有一個很好的培訓涵蓋Android通訊錄訪問:http://developer.android.com/training/contacts-provider/index.html –

2

試試這個清潔迭代:

for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { 
    // do what you need with the cursor here 
} 

這是一個典型的關閉的一個錯誤。 Cursor.moveToFirst()已將光標移至第一個位置,然後Cursor.moveToNext()將其移至下一個跳過第一個位置的位置。

爲了讓你的代碼工作從您的代碼刪除Cursor.moveToFirst()

在一個側面說明,如果你尋找對付光標和內容提供商的更清潔的方式嘗試這個庫:https://github.com/futuresimple/android-db-commons

這將你的代碼的重要組成部分更改爲類似這樣:

numberList = ProviderAction.query(CommonDataKinds.Phone.CONTENT_URI) 
     .projection(CommonDataKinds.Phone.DISPLAY_NAME, 
      CommonDataKinds.Phone.NUMBER, 
      CommonDataKinds.Phone.LABEL) 
     .perform(getContentResolver()) 
     .toFluentIterable(new Function<Cursor, ContactPhoneItems>() { 
      @Override 
      public ContactPhoneItems apply(Cursor cursor) { 
      ContactPhoneItems item = new ContactPhoneItems(); 
      item.setNumber(cursor.getString(cursor.getColumnIndexOrThrow(CommonDataKinds.Phone.NUMBER))); 
      item.setPhoneType(cursor.getString(cursor.getColumnIndexOrThrow(CommonDataKinds.Phone.LABEL))); 
      return item; 
      } 

     }) 
     .filter(new Predicate<ContactPhoneItems>() { 
      @Override 
      public boolean apply(ContactPhoneItems contactPhoneItems) { 
      return !TextUtils.isEmpty(contactPhoneItems.getNumber()); 
      } 
     });