与联系人照片联系人列表创建性能问题 [英] Contact List with Contact Photo creates performance issue

查看:182
本文介绍了与联系人照片联系人列表创建性能问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的游标中读取联系人数据,并试图将其加载到一个ListView

I am fetching Contact Data using cursor and trying to load it in a ListView

我已经根据<发达的我的code href=\"http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/QuickContactsDemo.html\"相对=nofollow> APIDemos的QuickContact 样品(API等级8级)

I have developed my code based on QuickContact sample of APIDemos (API Level 8)

和这里是我的code,我已经修改了一点,但我所面临的性能问题
如果我删除联系人照片code,那么性能将被罚款,否则它太慢的像拖着一个列表

and here is my code which i have modified a bit , but i am facing the performance issue if i remove the contact photo code then performance will be fine otherwise its too slow like dragging a list

适配器code

    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);
        }
}

获取联系code

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);
}

请注意:
我通过这个线程了,但我们都使用不同的方法
负荷联系人照片在ListView效果

修改

我把它写下来以下code,但调用

I have write it down following code but calling

imageDownloader.download(contactUri, 
(ImageView) cache.photoView , 
getContentResolver(), 
contactId);

下载图片code

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();
                }
            }

        }

    }

但是,我用这code和我快速向下滚动,几秒钟后,问题
该QuickBadgeContact控件加载,在这之前没有出现在QuickBadgeContact那占位符。

But the problem that i am using this code and i scroll down fast , after few second the QuickBadgeContact widget is loading , before that nothing appears in that placeholder of QuickBadgeContact.

看到图片

有时会出现图像后相当长的,看看这里

sometimes images appears after quite long , look here

所以它不是工作在android系统工作的方式联系的ListView,如果我们ASLO QuickBadgeContact将有默认,并作为一个占位符,后来就QuickBadgeContact负荷内的图像通过,但在我的code整个徽章滚动那么快很多几秒钟后出现

so its not working the way Contact ListView in android work , if we scroll much faster then aslo QuickBadgeContact will there by default and act as a placeholder , image inside the QuickBadgeContact loads later on but in my code the whole badge appears after a few seconds

我只需要加载图像保存为一个具有照片的接触,并让其他不变,因为这是装在没有图像发现用户BLACK位图,但我不知道我会怎么做THT <? / STRONG>

I just need to keep loading images to the contact which has a photo , and let the other untouched as this is loading BLACK bitmap where no image is found for user but i dont know how would i do tht ?

推荐答案

我觉得延迟加载是给你答案。
这是通过使用一个ScrollListener为您的ListView实施

I think lazy loading is the answer for you. This is implemented using a ScrollListener for your ListView.

在活动,它看起来类似的东西:

In the Activity it looks something like that:

public class ListViewActivity extends Activity {

    public boolean mBusy = false;
    // even more initializing

    @Override
    public void onCreate(Bundle savedInstanceState) {
        // The code to build the activity
        ListView listView = findViewById(R.id.ListView);
        listView.setOnScrollListener(listViewOnScrollListener);
        listView.setAdapter(new ContactListAdapter(this, R.layout.whatsoever, null)
        // it is important to give the Adapter 'this' as context because we need the mBusy boolean
        // we should populate the adapter later in onCreate...
        // even more code
    }

    private AbsListView.OnScrollListener listViewOnScrollListener = new AbsListView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(AbsListView absListView, int scrollState) {
            if (absListView instanceof ListView) {
                ListView listView = (ListView)absListView;
                switch (scrollState) {
                case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:
                    mBusy = false;
                    // Find out which elements of the ListView are visible to the user
                    int first = listView.getFirstVisiblePosition();
                    int childMargin = 0;
                    if (first < listView.getHeaderViewsCount()) {
                        first = listView.getHeaderViewsCount();
                        childMargin = listView.getHeaderViewsCount();
                    }
                    int last = listView.getLastVisiblePosition();
                    if (last > (listView.getCount() - listView.getFooterViewsCount() - 1)) {
                        last = listView.getCount() - listView.getFooterViewsCount() - 1;
                    }

                    for (int i = first; i <= last; i++) {
                        // This is for only populating the visible items of the list
                        // Action to perform the loading of your contactPhoto
                        // or displaying it
                        // maybe you call a method from the adapter to populate the views
                        adapter.loadImageBadges(listView.getChildAt(i - first + childMargin)),i);  
                    }
                    break;
                case AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
                    mBusy = true;
                    break;
                case AbsListView.OnScrollListener.SCROLL_STATE_FLING:
                    mBusy = true;
                    break;
                }
            }
        }

        @Override
        public void onScroll(AbsListView absListView, int i, int i1, int i2) {
            // Do something when the list is scrolling
        }
      };

    // The rest of the activity code

}

适配器将获得额外的code:

The adapter will get additional code:

private class ContactListAdapter extends ResourceCursorAdapter {

    public ContactListAdapter(Context context, int layout, Cursor c) {
        super(context, layout, c);
        cur = c;
    }

    @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;           
        cur.copyStringToBuffer(cur.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME), cache.nameBuffer);
        int size = cache.nameBuffer.sizeCopied;
        cache.nameView.setText(cache.nameBuffer.data, 0, size);          

        if (!context.mBusy) {
            // Do the expensive things only if the list is not scrolling...
            loadImageBadges(convertView, arg2.getPosition())
        } else {
            // initialize with dummy data
        }
    }

    public void ImageBadges(View view, int position) {
        final ContactListItemCache cache = (ContactListItemCache) view.getTag();
        QuickContactBadge photoView = cache.photoView;            
        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));
    }

    // The rest of the adapter code

}

通过采用这种code你变懒加载只填充当前可见的意见,所以你提到的表现应该只是增加。

By adopting this code you get lazy loading which only populates the currently visible views, so performance should increase just as you mentioned.

这将使也感觉到一个额外的事情是缓存中检索照片的方式,当光标加载它。

One additional thing which would make also sense is a way to cache the photos retrieved when the cursor loads it.

编辑:

上面提到的code是借来的,并在<一个采用了Android的样本href=\"http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/view/List13.html\" rel=\"nofollow\">http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/view/List13.html - >慢适配器

The code mentioned above is borrowed and adopted out of the Android Samples at http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/view/List13.html -> Slow adapter

编辑2:

我同意鲁本Scratton 为把辛勤工作的一部分适配器(如图像处理)成另一个线程。

I agree to Reuben Scratton for putting the hard working part of the adapter (such as Image processing) into another thread.

这篇关于与联系人照片联系人列表创建性能问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆