android - 带有联系人照片的联系人列表会造成性能问题

标签 android android-widget bitmap android-listview

我正在使用游标获取联系人数据并尝试将其加载到 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 的占位符中没有任何内容。

看图

enter image description here

有时候过段时间会出现图片,看这里

enter image description here

所以它的工作方式与 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/

相关文章:

android - RTSP 安卓媒体播放器

Android - 如何加载大图像(将其转换为较小的尺寸)并将其作为 Base64 字节数组发送(避免 OutOfMemory 错误)

android - 如何使用此传感器 API 中的磁力计?

android - Android 5.1 上的 Adreno 420 驱动程序错误

php - 使用 PHP 和 ImageMagick 以编程方式将 RGB 图像转换为 1 位灰度 (b/w) 位图图像

android - 如何在不首先读取整个图像的情况下就地缩放流式位图?

java - 将图片保存到变量中

android - ADB 在连接时将 Motorola Xoom 显示为离线

Android Widget 更新 TextView 文本

android - Android 上的缩放小部件(dp、px、屏幕尺寸)