CursorWindow读取失败(行1列-1),联系人查询代码报错求助
问题排查:CursorWindow读取第-1列异常
这个问题本质是查询的列和实际要读取的列不匹配导致的,咱们一步步拆解清楚:
核心原因
你调用getContentResolver().query()时,第二个参数(指定要查询的列)只传了ContactsContract.Data.LOOKUP_KEY这一列,但后续代码却尝试读取ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME和ContactsContract.CommonDataKinds.Phone.NUMBER——这两个列根本没被包含在查询结果里!
当c.getColumnIndex(列名)找不到对应列时,会返回-1,这时候调用c.getString(-1)自然就抛出了"无法从拥有3行1列的CursorWindow中读取第1行第-1列"的异常。
另外还有个小疏漏:你的循环先调用c.moveToFirst()后直接用while(c.moveToNext()),会跳过第一行数据,这点也要修正。
解决方法
1. 修正查询投影,加入需要的列
把你要读取的姓名、号码都加到投影参数里,同时建议过滤出电话类型的数据,避免读取到联系人的其他类型数据(比如邮箱、地址):
2. 修正循环逻辑,避免跳过首行
用do-while循环或者先判断moveToFirst()后再用while,同时记得关闭Cursor、处理空指针。
完整修正代码
// 定义需要查询的所有列 String[] projection = { ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER, ContactsContract.Data.LOOKUP_KEY // 如果不需要这个列可以直接删掉 }; // 只查询电话类型的联系人数据 String selection = ContactsContract.Data.MIMETYPE + " = ?"; String[] selectionArgs = { ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE }; Cursor c = getContentResolver().query( ContactsContract.Data.CONTENT_URI, projection, selection, selectionArgs, null ); contacts = new ArrayList<String>(); phno = new ArrayList<String>(); // 先判断Cursor是否为空,避免空指针异常 if (c != null && c.moveToFirst()) { do { // 读取姓名和号码 String contactname = c.getString(c.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); String phnumber = c.getString(c.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); contacts.add(contactname); phno.add(phnumber); // 别忘了把号码也加入列表 } while (c.moveToNext()); // 用完Cursor一定要关闭,防止内存泄漏 c.close(); }
额外提醒
- 别忘了在
AndroidManifest.xml中添加联系人读取权限:<uses-permission android:name="android.permission.READ_CONTACTS" /> - 在Android 6.0(API 23)及以上版本,需要动态申请这个权限,否则会直接报错。
内容的提问来源于stack exchange,提问作者saikumar kolisetty
相关产品推荐
相关产品推荐

