如何在android上快速加载listview中的联系人
在我的应用程序中,我在列表视图中列出联系人。触点数量为1000+。我有联系人 通过使用ContentResolver query即cr.query(…),将值存储在arraylist中 然后在setListAdapter(…)中加载数组列表。显示我的所有联系人 应用程序需要将近1分钟的时间,所以我使用异步任务,但是使用异步任务没有太大的区别 我需要在2到4秒内显示所有联系人。我签入默认联系人 android模拟器上的应用程序,可在2到4秒内加载。我已花费 在谷歌呆了很长时间。但我找不到任何有用的解决办法。请帮助我如何快速加载listview上的联系人。请帮帮我 我的编码示例:如何在android上快速加载listview中的联系人,android,android-listview,android-contacts,Android,Android Listview,Android Contacts,在我的应用程序中,我在列表视图中列出联系人。触点数量为1000+。我有联系人 通过使用ContentResolver query即cr.query(…),将值存储在arraylist中 然后在setListAdapter(…)中加载数组列表。显示我的所有联系人 应用程序需要将近1分钟的时间,所以我使用异步任务,但是使用异步任务没有太大的区别 我需要在2到4秒内显示所有联系人。我签入默认联系人 android模拟器上的应用程序,可在2到4秒内加载。我已花费 在谷歌呆了很长时间。但我找不到任何有用的
private ArrayList<ContactListEntry> loadContactListInternal(String searchString) {
ArrayList<ContactListEntry> contactList = new ArrayList<ContactListEntry>();
ContentResolver cr = getContentResolver();
Cursor cur = null;
String[] projection = new String[] {BaseColumns._ID,ContactsContract.Contacts.DISPLAY_NAME,ContactsContract.Contacts.PHOTO_ID};
....
cur=cr.query(ContactsContract.Contacts.CONTENT_URI, projection, selection, null, ContactsContract.Contacts.DISPLAY_NAME + " ASC");
while (cur.moveToNext()) {
int id = Integer.parseInt(cur.getString(0));
....
if (input !=null)
photo = BitmapFactory.decodeStream(input);
....
ArrayList<ContactListEntry.PhoneEntry> phoneEntries = new ArrayList<ContactListEntry.PhoneEntry>();
String[] projection1 = new String[] {ContactsContract.CommonDataKinds.Phone.NUMBER,ContactsContract.CommonDataKinds.Phone.TYPE};
Cursor pcur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,projection1, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[] { String.valueOf(id) }, null);
while (pcur.moveToNext()) {
...
}
pcur.close();
ContactListEntry entry = new ContactListEntry(id, name, photo, phoneEntries);
contactList.add(entry);
}
cur.close();
return contactList;
}
.....
in another class
private void selectionUpdated() {
....
setListAdapter(new SelectedArrayAdapter(this, app.selectedContacts));
...
}
private ArrayList loadContactListInternal(字符串搜索字符串){
ArrayList contactList=新建ArrayList();
ContentResolver cr=getContentResolver();
游标cur=null;
字符串[]投影=新字符串[]{BaseColumns.\u ID,ContactsContract.Contacts.DISPLAY\u NAME,ContactsContract.Contacts.PHOTO\u ID};
....
cur=cr.query(ContactsContract.Contacts.CONTENT_URI,投影,选择,null,ContactsContract.Contacts.DISPLAY_NAME+“ASC”);
while(cur.moveToNext()){
int id=Integer.parseInt(cur.getString(0));
....
如果(输入!=null)
photo=BitmapFactory.decodeStream(输入);
....
ArrayList phoneEntries=新的ArrayList();
String[]projection1=新字符串[]{ContactsContract.CommonDataTypes.Phone.NUMBER,ContactsContract.CommonDataTypes.Phone.TYPE};
游标pcur=cr.query(ContactsContract.CommonDataTypes.Phone.CONTENT\u URI,projection1,ContactsContract.CommonDataTypes.Phone.CONTACT\u ID+“=?”,新字符串[]{String.valueOf(ID)},null);
while(pcur.moveToNext()){
...
}
pcur.close();
ContactListEntry条目=新的ContactListEntry(id、姓名、照片、电话条目);
联系人列表。添加(条目);
}
cur.close();
返回联系人列表;
}
.....
在另一个班级
私有void selectionUpdated(){
....
setListAdapter(新建SelectedArrayAdapter(此应用程序为selectedContacts));
...
}
因此,您的问题是,您要为每个联系人执行许多子查询。我曾经有过同样的问题。我的情况是,我显示了许多联系人,并允许用户点击其中任何一个。之后,我开始在另一个活动中处理联系人
当时,我最终决定只显示名称,然后在启动下一个活动之前,懒洋洋地获取所有其他数据。这是惊人的:我的程序的速度几乎降低了200倍,用户完全看不到操作
如果我没有错的话,默认的android列表也会这样做——它只显示姓名,然后加载所有其他与联系人相关的数据。我使用游标适配器,剪切数据库,调整数组并优化代码。考虑只进行一次查询,并放弃子查询的想法(如前所述)。您只需使用内容Uri进行查询即可实现速度:
"ContactsContract.CommonDataKinds.Phone.CONTENT_URI"
此URI还具有“ContactsContract.Contacts.DISPLAY\u NAME”字段
您可能还想考虑执行这个查询并在一个单独的线程中处理适配器,使其完全透明。
这对我很有效。这里的优化解决方案
private static final String[] PROJECTION = new String[] {
ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER
};
.
.
.
ContentResolver cr = getContentResolver();
Cursor cursor = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, PROJECTION, null, null, null);
if (cursor != null) {
try {
final int nameIndex = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
final int numberIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
String name, number;
while (cursor.moveToNext()) {
name = cursor.getString(nameIndex);
number = cursor.getString(numberIndex);
}
} finally {
cursor.close();
}
}
干杯…:)使用投影和选择参数的概念,在我的案例中检索500个联系人,最初需要12秒 现在需要350毫秒(少于秒)
有关此链接的详细信息…您在列表视图中具体显示了什么?我在右侧显示联系人姓名和电话号码,并在下一个过程中存储其他值。下面是我们尝试提高性能的另一个线程:。正如你再次看到的,我是唯一敢于回答的人。OP没有找到任何更干净的解决方案是的,我使用两个查询来获取详细信息,这是在我获取id、名称的第一个查询中。。。在第二个查询中,我将联系人id作为参数传递,以获取电话号码和类型。但需要两个查询(即子查询)来获取电话号码和此类详细信息。是否有任何方法可以组合到一个查询中或在单个查询中获得所有详细信息?请回答我的问题。@murali_ma您不能使用两个查询。您可以使用
n+1
查询,其中n是手机中的联系人数。我将对此进行更多的研究,但当时我尝试了与你的想法相同的方法,但徒劳无功。你能解释一下,我是如何遇到同样的问题的吗。我目前正在使用数组适配器。@Vikas Rana,我的数据在游标(数据库)中,所以我使用了游标适配器,在您的情况下,您在arraylist中有多少数据?我正在arraylist中添加电话号码、姓名和联系人照片,而没有将其存储到数据库中。您能解释一下如何添加吗?
void getAllContacts() {
long startnow;
long endnow;
startnow = android.os.SystemClock.uptimeMillis();
ArrayList arrContacts = new ArrayList();
Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
String selection = ContactsContract.Contacts.HAS_PHONE_NUMBER;
Cursor cursor = ctx.getContentResolver().query(uri, new String[]{ContactsContract.CommonDataKinds.Phone.NUMBER, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone._ID, ContactsContract.Contacts._ID}, selection, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
cursor.moveToFirst();
while (cursor.isAfterLast() == false) {
String contactNumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
String contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
int phoneContactID = cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone._ID));
int contactID = cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts._ID));
Log.d("con ", "name " + contactName + " " + " PhoeContactID " + phoneContactID + " ContactID " + contactID)
cursor.moveToNext();
}
cursor.close();
cursor = null;
endnow = android.os.SystemClock.uptimeMillis();
Log.d("END", "TimeForContacts " + (endnow - startnow) + " ms");
}