使用Glide库设置当图片加载完成后进度条消失的可见性

110

嗨,我想为图像添加一个进度条,在图像加载时显示,但当图像加载完成后我想将其设置为隐藏。之前我使用的是Picasso库来实现这一点。但我不知道如何在Glide库中使用它。我知道有一些准备好的资源函数可用,但我不知道如何使用它。有人能帮帮我吗?

Picasso库的代码

Picasso.with(mcontext).load(imgLinkArray.get(position).mUrlLink)
       .into(imageView, new Callback() {
           @Override
           public void onSuccess() {
               progressBar.setVisibility(View.GONE);
           }

           @Override
           public void onError() {
           }
        })
;

现在我该如何使用Glide完成这个任务?

Glide.with(mcontext).load(imgLinkArray.get(position).mUrlLink)
     .into(imageView);

我可以使用 Glide 来加载图像,但如果图像加载完毕后,我要如何在代码中写入 progressBar.setVisibility(View.GONE); 呢?


2
你为什么改用其他库了?Picasso很棒啊。 - tasomaniac
我也建议除非你有充分的理由更换库,否则应坚持使用Picasso。 - Chris
13个回答

263

这个问题比较老了,我不知道当时使用Glide的情况如何,但是现在可以通过监听器轻松实现(而不是采用被选为正确答案的建议方式)。

progressBar.setVisibility(View.VISIBLE);
Glide.with(getActivity())
     .load(args.getString(IMAGE_TO_SHOW))
     .listener(new RequestListener<String, GlideDrawable>() {
         @Override
         public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
             return false;
         }

         @Override
         public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
             progressBar.setVisibility(View.GONE);
             return false;
         }
     })
     .into(imageFrame)
;

如果您想自己处理动画,则返回true;如果希望Glide为您处理动画,则返回false。


16
onException 中也应考虑隐藏 progressBar,否则它会无限旋转并给出错误的希望。一旦调用了 onException,Glide 将不会执行除设置传递给 .error() 的内容之外的任何操作。 - TWiStErRob
2
如果在图像加载完成之前离开片段/活动,则可能会导致NullPointerException。 - aProperFox
1
我并不是在敦促你创建内部类监听器,只是为了展示一种最简洁的完成任务的工具。 - Yaroslav
1
当然,我通过在调用super之前在onDestroyView()中添加一个Glide.clear(yourImageView)的调用来解决这个问题。 - aProperFox
10
注意:在调用.into()之前必须先调用.listener - Ahmed Mostafa

52

如果你想在Kotlin中做到这一点,你可以尝试这样做:

    Glide.with(context)
            .load(url)
            .listener(object : RequestListener<Drawable> {
                override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
                    //TODO: something on exception
                }
                override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
                    Log.d(TAG, "OnResourceReady")
                    //do something when picture already loaded
                    return false
                }
            })
            .into(imgView)

17
也需要引入Target: import com.bumptech.glide.request.target.Target - Gibolt
@Gibolt 这个问题困扰了我整整10分钟。 - johnrao07
为什么我们要返回false? - undefined

17
我的回答基于过时的API。请参见此处获取更新的答案。

.listener() 更好,因为您将收到有关负载的更多信息(模型、内存缓存等),因此更容易决定更多自定义逻辑。RequestListener 也更稳定,覆盖哪个 Target 创建不会给您带来未来修复的好处。您还可以轻松创建一个 VisibilityListener<T, R>,并在不同的上下文中重复使用它。 - TWiStErRob

9

在异常情况下,加入条件以再次显示ProgressBar

 Glide.with(context)
    .load(image_url)
    .listener(new RequestListener<String, GlideDrawable>() {
        @Override
        public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
            if(e instanceof UnknownHostException)
                progressBar.setVisibility(View.VISIBLE);
            return false;
        }

        @Override
        public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
            progressBar.setVisibility(View.GONE);
            return false;
        }
    })
    .into(imageView);

9

对我来说,上述解决方案也非常有效,但是当我使用asBitmap()下载图像时,它不起作用。

我们需要使用BitmapImageViewTarget。

Glide.with(this) .load(imageURL)
 .asBitmap()
 .placeholder(R.drawable.bg)
 .into(new BitmapImageViewTarget(imageView) {
            @Override
            public void onResourceReady(Bitmap  drawable, GlideAnimation anim) {
                super.onResourceReady(drawable, anim);
                progressBar.setVisibility(View.GONE);
            }
        });

请看我的评论:https://dev59.com/kV8e5IYBdhLWcg3wHnks#dKgUoYgBc1ULPQZFkd1d。这个答案很好地展示了我在那里所说的内容。 - TWiStErRob

8

GlideDrawable已不再推荐使用,应使用简单的Drawable。

RequestOptions requestOptions = new RequestOptions();
requestOptions.placeholder(R.drawable.placeholder);
requestOptions.error(R.drawable.error);

Glide.with(getContext())
                 .setDefaultRequestOptions(requestOptions)
                 .load(finalPathOrUrl)
                 .listener(new RequestListener<Drawable>() {
                        @Override
                        public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                            progressBar.setVisibility(View.GONE);
                            return false;
                        }

                        @Override
                        public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
                            progressBar.setVisibility(View.GONE);
                            return false;
                        }
                    })
                 .into(mImageView);

6
在 Kotlin 中,您可以像以下这样操作。
Glide.with(context)
            .setDefaultRequestOptions(RequestOptions().placeholder(R.drawable.ic_image_placeholder).error(R.drawable.ic_image_placeholder))
            .load(url)
            .listener(object : RequestListener<Drawable>{
                override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
                    return false
                }

                override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
                    return false
                }

            })
            .into(imageView)

4

Kotlin的方式

showProgressBar()
Glide.with(context)
                .load(image_url)
                .listener(object : com.bumptech.glide.request.RequestListener<Drawable> {
                    override fun onLoadFailed(
                        e: GlideException?,
                        model: Any?,
                        target: Target<Drawable>?,
                        isFirstResource: Boolean
                    ): Boolean {
                        hideProgressBar()
                        return false
                    }

                    override fun onResourceReady(
                        resource: Drawable?,
                        model: Any?,
                        target: Target<Drawable>?,
                        dataSource: DataSource?,
                        isFirstResource: Boolean
                    ): Boolean {
                        img_product_banner.visibility = View.VISIBLE
                        hideProgressBar()
                        return false
                    }

                }).placeholder(R.drawable.placeholder)
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .into(img_product_banner)

3

更新:

Glide.with(this)
            .load(imageUrl)
            .listener(new RequestListener<Drawable>() {
                @Override
                public boolean onLoadFailed(@Nullable final GlideException e,
                                            final Object model, final Target<Drawable> target,
                                            final boolean isFirstResource) {
                    showProgress(false);

                    mNoContentTextView.setVisibility(View.VISIBLE);

                    return false;
                }

                @Override
                public boolean onResourceReady(final Drawable resource, 
                                               final Object model, 
                                               final Target<Drawable> target, 
                                               final DataSource dataSource, 
                                               final boolean isFirstResource) {
                    showProgress(false);

                    mNoContentTextView.setVisibility(View.GONE);
                    mContentImageView.setImageDrawable(resource);

                    return false;
                }
            })
            .into(mContentImageView);

如果你已经有了onResourceReady,那么"into"有什么用?我不能只使用监听器吗? 如果可以,那么如何使它开始加载而不需要"into"? - android developer
作为一名 Android 开发者,我知道你可以在不使用 into 的情况下进行操作。 - Narek Hayrapetyan
它值得一试 - Narek Hayrapetyan
但是如果我不使用“into”,我认为它会发出警告。 - android developer

3

我是如何做到事情更简单,代码更干净的。

例子:

progress_bar.visibility = View.VISIBLE

profilePicturePath?.let {
    GlideApp.with(applicationContext)
        .load(CloudStorage.pathToReference(it))
        .placeholder(R.drawable.placeholder)
        .listener(GlideImpl.OnCompleted {
            progress_bar.visibility = View.GONE
        })
    .into(profile_picture)
} ?: profile_picture.setImageResource(R.drawable.placeholder)

使用方法:

GlideImpl.OnCompleted {
    // completed
}

只需将 GlideImpl.OnCompleted { } 传递给 Glide 的 .listener() 方法即可。

GlideImpl.kt 类接受 Glide 的 RequestListener。

import android.graphics.drawable.Drawable
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.target.Target

object GlideImpl {

    object OnCompleted : RequestListener<Drawable> {

        private lateinit var onComplete: () -> Unit

        operator fun invoke(onComplete: () -> Unit): OnCompleted {
            OnCompleted.onComplete = { onComplete() }
            return this
        }

        override fun onResourceReady(
            resource: Drawable?,
            model: Any?,
            target: Target<Drawable>?,
            dataSource: DataSource?,
            isFirstResource: Boolean
        ): Boolean {
            onComplete()
            return false
        }

        override fun onLoadFailed(
            e: GlideException?,
            model: Any?,
            target: Target<Drawable>?,
            isFirstResource: Boolean
        ): Boolean {
            onComplete()
            return false
        }
    }
}

就是这样了!


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