我正在使用游标获取联系人数据并尝试将其加载到 ListView 中
我已经根据 QuickContact 开发了我的代码APIDemos 示例(API 级别 8)
这是我修改过的代码,但我遇到了性能问题 如果我删除联系人照片代码,那么性能会很好,否则它太慢了,就像拖动列表一样
适配器代码
private class ContactListAdapter extends ResourceCursorAdapter{
Cursor cur;
public ContactListAdapter(Context context, int layout, Cursor c) {
super(context, layout, c);
cur = c;
// TODO Auto-generated constructor stub
}
@Override
public void bindView(View view, Context arg1, Cursor arg2) {
// TODO Auto-generated method stub
final ContactListItemCache cache = (ContactListItemCache) view.getTag();
TextView nameView = cache.nameView;
QuickContactBadge photoView = cache.photoView;
cur.copyStringToBuffer(cur.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME), cache.nameBuffer);
int size = cache.nameBuffer.sizeCopied;
cache.nameView.setText(cache.nameBuffer.data, 0, size);
long contactId = cur.getLong(cur.getColumnIndex(ContactsContract.Contacts._ID));
Uri contactUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, String.valueOf(contactId));
InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(getContentResolver(), contactUri);
cache.photoView.setImageBitmap(BitmapFactory.decodeStream(input));
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View view = super.newView(context, cursor, parent);
ContactListItemCache cache = new ContactListItemCache();
cache.nameView = (TextView) view.findViewById(R.id.name);
cache.photoView = (QuickContactBadge) view.findViewById(R.id.badge);
view.setTag(cache);
return view;
}
}
final static class ContactListItemCache {
public TextView nameView;
public QuickContactBadge photoView;
public CharArrayBuffer nameBuffer = new CharArrayBuffer(128);
}
}
获取联系人代码
private Cursor getContacts()
{
// Run query
Uri uri = ContactsContract.Contacts.CONTENT_URI;
String[] projection = new String[] {
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts.LOOKUP_KEY
};
String selection = ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '" +
(mShowInvisible ? "0" : "1") + "'";
String[] selectionArgs = null;
String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
return managedQuery(uri, projection, selection, selectionArgs, sortOrder);
}
注意: 我经历了这个线程,但我们都使用不同的方法 Load contact photo in a listview performance
编辑
我已经按照代码写下来但是调用
imageDownloader.download(contactUri,
(ImageView) cache.photoView ,
getContentResolver(),
contactId);
下载图片代码
Bitmap downloadBitmap(Uri url) {
final int IO_BUFFER_SIZE = 4 * 1024;
InputStream inputStream = null;
try {
inputStream = ContactsContract.Contacts.openContactPhotoInputStream(resolver, url);
if(inputStream ==null){
return BitmapFactory.decodeStream(inputStream);
}else
{
return BitmapFactory.decodeStream(new FlushedInputStream(inputStream));
}
// return BitmapFactory.decodeStream(inputStream);
// Bug on slow connections, fixed in future release.
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
但问题是我正在使用这段代码,几秒钟后我快速向下滚动 QuickBadgeContact 小部件正在加载,在此之前,QuickBadgeContact 的占位符中没有任何内容。
看图
有时候过段时间会出现图片,看这里
所以它的工作方式与 android 中的 Contact ListView 不同,如果我们滚动得更快,那么 aslo QuickBadgeContact 将默认在那里并充当占位符,QuickBadgeContact 中的图像稍后加载,但在我的代码中,整个徽章出现在几秒钟
我只需要继续将图像加载到有照片的联系人,并让其他人保持不变,因为这是在加载黑色位图,但没有为用户找到图像,但我不知道我该怎么做?强>
最佳答案
保持应用程序响应有一个简单的规则:不要在 UI 线程上执行 I/O。您的 bindView() 实现违反了规则,因为它从数据库中读取位图。当慢速 I/O 操作完成时,主线程被阻塞。
您应该创建 AsyncTasks 来加载图像。最佳实践 AFAIK 是在您的应用程序中有一个完全可重用的 ImageCache 类......使用这样的方法:
public static void getImage(Uri imageUri, ImageView imageView);
即你给它一个 URI 和一个 ImageView 引用,它会负责在后台线程上下载图像并在准备就绪时更新 ImageView。
比这稍微多一点...需要取消未完成的请求,并且您应该将 ImageView 保存在 WeakReferences 中以避免泄漏它所属的 Activity(有一篇关于此的 Android 开发者博客文章)。
关于android - 带有联系人照片的联系人列表会造成性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9340039/