Glide如何异步加载图片?

6

我有一个RecyclerView,每个RecyclerView的项目都有一个ImageView。 我使用Glide在该ImageView中加载图像。 我看到一些博客说Glide可以异步加载图像,但是从下面的代码中我看不出来。它似乎只在调用onBindViewHolder时加载一个图像。 它如何显示异步性?

   public class GalleryAdapter extends RecyclerView.Adapter<GalleryAdapter.ViewHolder> {
        private Context mContext;
        private List<GalleryItem> mList;

        public GalleryAdapter(Context mContext, List<GalleryItem> mList) {
            this.mContext = mContext;
            this.mList = mList;
        }

        public static class ViewHolder extends RecyclerView.ViewHolder {
            public ImageView mImageView;
            public ViewHolder(View itemView) {
                super(itemView);
                mImageView = (ImageView) itemView.findViewById(R.id.gallery_item);
            }
        }

        @Override
        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_gallery,
                parent, false);
            ViewHolder vh = new ViewHolder(v);
            return vh;
        }

        @Override
        public void onBindViewHolder(ViewHolder holder, int position) {
            GalleryItem item = mList.get(position);
            holder.mImageView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                }
            });
            Glide.with(mContext)
                    .load(item.getUrl())
                    .thumbnail(0.5f)
                    .into(holder.mImageView);
        }

        @Override
        public int getItemCount() {
            return mList.size();
        }

        public void addAll(List<GalleryItem> newList) {
            mList.addAll(newList);
        }

        public void clear() {
            mList.clear();
        }
    }

当您滚动RecyclerView时,onBindViewHolder()会被多次调用以加载每个项目,并且对于每个项目,Glide都会在一个线程中下载图像并将其设置到imageView中,甚至它还负责图像缓存。 - Akshay Bhat 'AB'
@dashenswen,你所读的引用并不是指你提供的代码。它是关于Glide在幕后如何进行异步工作的。基本上,Glide会创建特定数量的线程,并且加载和缓存以队列的形式组织。 - Enzokie
@AkshayBhat'AB'。是的,我又读了一遍文档,对它印象深刻。顺便问一下,你知道他们为什么可以缓存那么多照片吗?文档说Glide在内存中缓存图像。但是当我滚动我的RecycleView并下载5000多张图片时,它没有OOM问题。你知道为什么吗?即使Glide以较低的质量下载图像,在这一点上也真的让我印象深刻。 - dashenswen
@Enzokie。感谢您的澄清。您知道为什么它可以加载这么多图片而没有OOM问题吗?Glide会下载质量较低的图像,但我可以在内存中保留至少5000张图片(应该比这更多)。 - dashenswen
@dashenswen 这是因为它使用了一种称为LRU(最近最少使用)的数据结构。当内存满时,它会销毁旧的图像以释放一些内存空间,然后加载最新下载的图像。另外,Glide通过去除一些颜色来减小图像大小,以节省空间(不过仅凭肉眼很难察觉到)。 - Enzokie
显示剩余2条评论
2个回答

2
根据glide文档这里这里的说明,应该使用返回FutureTarget而不是返回Target的into()方法。该方法需要宽度和高度,而不是ImageView:"如果您实际上想在后台线程中与解码图像交互,而不是使用downloadOnly,您可以使用返回FutureTarget的into()版本。" 请注意保留HTML标签。

2
我不是很理解你的解释。这与解释Glide如何异步加载图像有关吗? - dashenswen
不是很好的解释,我真的很想知道这个答案怎么得到了3个赞,它与问题无关,虽然它是正确的,但不适用于这个问题。 - Mohammad Elsayed

0

当您将图像加载到ImageView时,load方法会异步执行其工作,请查看以下线程:

  1. https://github.com/bumptech/glide/issues/1209
  2. https://github.com/bumptech/glide/wiki/Loading-and-Caching-on-Background-Threads
在第三个线程中,它提到了如何使图像的“同步”加载用于后台线程,这意味着默认情况下是异步进行的。
Bitmap myBitmap = Glide.with(applicationContext)
    .load(yourUrl)
    .asBitmap()
    .centerCrop()
    .into(500, 500)
    .get()

同时它也表明这个调用不能在主线程中执行,但当他们谈论正常的加载到 imageView 时,并没有提到这一点,这也是正常加载是异步完成的证据,然后自动地将结果移动到主线程以供 into(imageView) 方法使用。

我真的尝试找到明确的说明,但在文档中找不到任何信息,因此我认为这很明显,因为他们没有告诉我们如何像上面提到的情况一样管理后台线程。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接