尽管使用了ViewHolder,LazyLoader和简单的布局,但仍会出现口吃 [英] Stuttering Listview despite ViewHolder, LazyLoader and simple Layout

查看:78
本文介绍了尽管使用了ViewHolder,LazyLoader和简单的布局,但仍会出现口吃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个列表视图,可将服务器中的图像加载到ImageView中. Listview实现了viewholder模式,并具有非常简单的行相对布局. 对于延迟图像加载,我已经尝试了UniversalImageloader,毕加索,并且目前正在使用基于Google Volley的glide,该滑动应该很快.但是:用服务器映像替换占位符映像时,我的列表视图仍然断断续续,我只是想不通为什么,这是我的适配器代码:

I have a listview that loads images from a server into an ImageView. The Listview implements the viewholder pattern and has a very simple relative-layout for the rows. For lazy image loading, I have tried universalimageloader, picasso and am currently using glide, which is based on google volley, which should be blazing fast. However: My listview still stutters while replacing the placeholder image with the servers image and I just cant figure out why, here is my adapter-code:

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View rowView = convertView;
        News newsItem = getItem(position);

        if (rowView == null) {
            LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            rowView = inflater.inflate(mResource, null);
            // Create a viewHolder enabled row
            NewsViewHolder viewHolder = new NewsViewHolder();
            viewHolder.newsTitle = (TextView) rowView.findViewById(R.id.news_title);
            viewHolder.newsSubTitle = (TextView) rowView.findViewById(R.id.news_sub_title);
            viewHolder.newsDescription = (TextView) rowView.findViewById(R.id.news_desc);
            viewHolder.newsDate = (TextView) rowView.findViewById(R.id.news_date);
            viewHolder.newsThumb = (ImageView) rowView.findViewById(R.id.news_thumb);
            rowView.setTag(viewHolder);
        }
        NewsViewHolder holder = (NewsViewHolder) rowView.getTag();

        // Fill in fields of the current row of the NewsListView
        holder.newsTitle.setText(newsItem.title);
        holder.newsSubTitle.setText(newsItem.subTitle);
        holder.newsDescription.setText(newsItem.desciption);
        holder.newsDate.setText(SimpleDateFormat.getDateInstance().format(new Date(Long.parseLong(newsItem.date) * 1000)));

        Glide.load(newsItem.imageThumb)
                .centerCrop()
                .placeholder(R.drawable.placeholder)
                .into(holder.newsThumb);

        return rowView;
    }
}

/*
 * ViewHolder class for NewsListView
 */
public static class NewsViewHolder {
    public TextView newsTitle;
    public TextView newsSubTitle;
    public TextView newsDescription;
    public TextView newsDate;
    public ImageView newsThumb;
}

仅当我第一次滚动列表时,该列表才会结结巴巴,因此当我检索图像并将其滑动粘贴到列表中时.在将图像粘贴到列表视图中之后,滚动就像从一开始就应该是黄油般平滑.

The list only stutters while i am scrolling it for the first time, so when my images are retrieved and pasted into the list by glide. After the images are pasted into the listview scrolling is buttery smooth as it should be from the start.

我做错了什么?我如何有效地找出导致挂断的原因?我不是Traceview专家,它正在生成大量数据以供筛选.

What did I do wrong? How can I efficiently find out what is causing the hangup? I am not an expert in Traceview and it is producing a lot of data to sift through.

感谢您的帮助!

推荐答案

ImageView连续请求布局可能导致卡顿.参见ImageView.setImageDrawable:

Stuttering can be caused by ImageView continuously requesting layout. See ImageView.setImageDrawable:

if (oldWidth != mDrawableWidth || oldHeight != mDrawableHeight) {
    requestLayout();
}

我可以看到单个列表项确实很复杂(5会花费大量时间进行布局,尤其是在每次图像加载时都布局整个列表的情况下.

I can see that a single list item is really complex (5 which takes a lot of time to lay out, especially if the whole list is laid out on every image load.

键是R.drawable.placeholder的大小.在第一次加载时,总是显示.placeholder(),因为必须从Glide磁盘缓存中读取图像(即:后台I/O).来回滚动将填充内存高速缓存,这将导致立即加载(没有后台线程),并且出于这个原因,也不会显示.placeholder().没有大小变化→否requestLayout().

The key is the size of the R.drawable.placeholder. On the first load the .placeholder() is always shown, because the image must be read from the Glide disk cache (that is: background I/O). Scrolling back and forth fills the memory cache which results in immediate loads (no background thread) and also the .placeholder() is not shown for this very reason → no size change → no requestLayout().

这也有助于您的ImageView具有固定的大小(假定为centerCrop()),这意味着Glide加载到此视图中的所有Bitmap的大小都相同,并且这些Bitmap将被回收,因此,池中的Bitmap与回收的行之间可能会有1:1的对应关系. 同样,当回收现有行时,ViewHolder会保存一个ImageView,该图像中已经显示了相同大小的图像,因此不会进行重新布局.

It also helps that your ImageView has a fixed size (assuming from centerCrop()) which means that all Bitmap loaded by Glide into this view will be the same size and these Bitmaps will be recycled, so you'll probably have a 1:1 correspondence between Bitmaps in the pool and your recycled rows. Also when an existing row is recycled the ViewHolder holds an ImageView that has a same sized image already displayed in it so there will be no re-layout.

注意:Glide不是基于Volley,可以通过volley-integration使用Volley,但是默认情况下它不依赖于Volley.尽管这个问题已经很老了,但也许您所说的在3.0之前是正确的.

Note: Glide is not based on Volley, there's a possiblity of using Volley via volley-integration, but by default it has no dependency on it. Though this question is quite old, maybe what you stated was true before 3.0.

这篇关于尽管使用了ViewHolder,LazyLoader和简单的布局,但仍会出现口吃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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