关于ListView异步加载图片导致图片显示混乱以及ListView效率问题探讨

前面看到有帖子中有人使用notifyDataSetChanged()来解决ListView中异步加载图片第一张图片显示错误问题。首先在数据源没有变化的情况下没有必要使用notifyDataSetChanged(),会导致调用requestLayout()重绘当前界面的列,就是重新走getView().所以notifyDataSetChanged()在图片都已下载缓存完的情况下正常显示了,但是因为重新刷新界面了导致了效率变低。其实要知道ListView图片混乱都是因为重用了ConvertView,但这个是ListView性能的关键。我们为什么说建议在ListView中使用ViewHolder,按我的理解其一是能够保存ConvertView中各个View的引用,使得不需要每次都findViewById严重影响效率,其二是我们可以拿到View的引用后使用setTag()和getTag()方法,道理跟ConvertView.setTag()和ConvertView.getTag()是一样的。所以在异步加载图片的时候我们给予ImageView一个Tag,在加载完成回调的时候根据这个Tag来判断是否要把图片设置到当前的ImageView中。
?
代码片段,双击复制
01
private final ArrayList<View> mActiveImages = new ArrayList<View>();

?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
@Override
        public View getView( int position, View convertView, ViewGroup parent) {
                ViewHolder holder = null ;
                if (convertView == null ) {
                        // inflate convertView
                        holder = new ViewHolder();
                        // initial holer,means findViewById
                        convertView.setTag(holder);
                } else {
                        holder = (ViewHolder)convertView.getTag();
                }
                // do your stuff
 
                // add first then load icon,make sure we have the image holding the icon is contained at mActiveImages
                mActiveImages.remove(holder.mIcon);
                mActiveImages.add(holder.mIcon);
                // set tag to imageview for not messing up the images
                holder.mIcon.setTag( "your tag" );
                // here load Icon
                 
                return convertView;
        }

另外要善于利用AbsListView.RecyclerListener接口,使用这个接口可以达到只更新当前界面那些列的图片以及释放其他资源。
?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
@Override
        public void onMovedToScrapHeap(View view) {
                ViewHolder holder = (ViewHolder)view.getTag();
                mActiveImages.remove(holder.mIcon);
        }
 
        @Override
        public void setIcon(ImageView image, String tag, Drawable drawable) {
                if (mActiveImages.contains(image) && tag.equals(image.getTag())) {
                        image.setImageDrawable(drawable);
                }
        }

以上是我的看法,欢迎指正。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在使用 ListView 异步加载图片时,可以通过以下步骤实现: 1. 创建一个自定义的适配器(Adapter)类,继承自 BaseAdapter。这个适配器将负责管理数据和视图的绑定。 2. 在适配器中,创建一个内部类 ViewHolder,用于保存列表项中的视图引用。这个类将包含一个 ImageView 用于显示图片。 3. 在适配器的 getView 方法中,获取当前列表项的数据,并更新 ViewHolder 中的 ImageView。 4. 在更新 ImageView 时,可以使用异步加载图片的第三方库,如 Glide 或 Picasso。这些库提供了简单的接口来加载网络图片,并且处理了图片的缓存和压缩等问题。 下面是一个简单的示例代码: ```java public class CustomAdapter extends BaseAdapter { private List<String> imageUrlList; private Context context; public CustomAdapter(Context context, List<String> imageUrlList) { this.context = context; this.imageUrlList = imageUrlList; } @Override public int getCount() { return imageUrlList.size(); } @Override public Object getItem(int position) { return imageUrlList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder; if (convertView == null) { convertView = LayoutInflater.from(context).inflate(R.layout.list_item, parent, false); viewHolder = new ViewHolder(); viewHolder.imageView = convertView.findViewById(R.id.image_view); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } String imageUrl = imageUrlList.get(position); // 使用 Glide 异步加载图片 Glide.with(context) .load(imageUrl) .placeholder(R.drawable.placeholder_image) // 加载显示的占位图 .error(R.drawable.error_image) // 加载失败显示的错误图 .into(viewHolder.imageView); return convertView; } static class ViewHolder { ImageView imageView; } } ``` 在上述示例代码中,CustomAdapter 是自定义的适配器类,其中的 getView 方法中使用了 Glide异步加载图片。你可以将 imageUrlList 替换为你自己的图片地址列表,并根据需要修改加载中和加载失败时显示图片资源。同时,记得在布局文件中定义好 ImageView 的 id。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值