我正在尝试查询联系电话号码和姓名。正如编写此方法一样,我非常确定它会为每个电话号码提供一个新的名称/号码条目。在我按原样工作后,我会担心在一个联系人下面列出数字......
我在第160行得到了一个游标索引超出界限错误,但不确定原因(联系方式仍然很新鲜)。我已经粘贴了弹出错误的方法以及logcat。
请帮我弄清楚这个错误。此外,如果您知道更有效的查询方式,我将非常感激。
提前致谢
编辑:
感谢格雷厄姆·博兰德,我看到我的简单错误是“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
修复:
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>();
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 :(得分: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());
}
});
答案 1 :(得分: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?。