110

Hi I want to have a progress bar for image which will shown while image loading but when image loading will be completed I want to set it to gone. Earlier I was using Picasso library for this. But I don't know how to use it with Glide library. I have idea that some resource ready function is there but I don't know how to use it. Can anyone help me?

Code for Picasso Library

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

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

Now How Can I do this with Glide?

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

I am able to load image by this with Glide but how can I write progressBar.setVisibility(View.GONE); somewhere in code if image get loaded?

TWiStErRob
  • 44,762
  • 26
  • 170
  • 254
Hari Ram
  • 3,098
  • 5
  • 23
  • 30

13 Answers13

261

Question is rather old, and I don't know what was the situation with glide in those times, but now it can be easily done with listener (not as proposed in the answer chosen as correct).

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

You return true if want to handle things like animations yourself and false if want glide to handle them for you.

TWiStErRob
  • 44,762
  • 26
  • 170
  • 254
Yaroslav
  • 4,750
  • 3
  • 22
  • 33
  • 16
    Consider hiding the `progressBar` in `onException` as well, otherwise it'll spin indefinitely giving false hope. Once `onException` is called Glide will do nothing other than set what's passed to `.error()`. – TWiStErRob Oct 21 '15 at 10:36
  • 2
    This can result in a NullPointerException if you leave the Fragment/Activity before the image loads. – aProperFox Mar 03 '16 at 20:25
  • 1
    I'm not agitating you to create inner-class listeners, just the most concise way to show a tool for acomplishing the task. – Yaroslav Mar 03 '16 at 20:58
  • 1
    Sure thing, I resolved this by adding a call in onDestroyVIew() before the super call to say Glide.clear(yourImageView) – aProperFox Mar 03 '16 at 21:16
  • 9
    NOTE: `.listener` must be called before `.into()` – Ahmed Mostafa Jan 23 '18 at 11:40
50

If you want to do this in KOTLIN, you can try that way:

    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)
Dmytro Rostopira
  • 10,588
  • 4
  • 64
  • 86
Paulina
  • 930
  • 8
  • 13
17

My answer was based on out-dated APIs. See here for the more up-to-date answer.

Community
  • 1
  • 1
Bryan Sills
  • 583
  • 1
  • 7
  • 21
  • `.listener()` is better because you'll receive more information about your load (model, memory cache, ...) so it's easier to decide more custom logic. `RequestListener` is also more stable, overriding which `Target` to create won't give you the benefit of future fixes. You can also easily create a `VisibilityListener` that you can re-use in different contexts. – TWiStErRob Oct 21 '15 at 10:39
9

The above solution works pretty well for me too but when i use asBitmap() to download the image. It does not work.

We need to use 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);
            }
        });
Pratap
  • 591
  • 8
  • 25
  • See my comment: http://stackoverflow.com/questions/26054420/set-visibility-of-progress-bar-gone-on-completion-of-image-loading-using-glide-l#comment54315331_26066582. This answer is a good demonstration of what I said there. – TWiStErRob Oct 21 '15 at 10:42
9

In exception put a condition for show again the 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);
V-rund Puro-hit
  • 5,518
  • 9
  • 31
  • 50
Alex Zaraos
  • 6,443
  • 2
  • 26
  • 21
8

GlideDrawable are deprecated, use simple 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);
Alex
  • 8,908
  • 28
  • 103
  • 157
6

In Kotlin you can do like below

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)
Android Dev
  • 1,496
  • 1
  • 13
  • 25
4

Kotlin way

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)
Aditya Patil
  • 1,287
  • 12
  • 19
3

Update:

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);
Narek Hayrapetyan
  • 1,731
  • 15
  • 27
3

How I did things. the shorter way, cleaner code

example:

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)

usage:

GlideImpl.OnCompleted {
    // completed
}

just pass GlideImpl.OnCompleted { } to the Glide's .listener()

GlideImpl.kt class that accepts Glide's 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
        }
    }
}

and that is it!

2
  1. In xml take progress bar with height & width(match_parent).
  2. Before call below mention method , set progress bar visibility Visible.

    public void setImageWIthProgressBar(Context context, final ImageView imageView, String imageUrl, final ProgressBar progressBar) {
    
            Glide.with(context)
                    .load(imageUrl)
                    .listener(new RequestListener<String, GlideDrawable>() {
                        @Override
                        public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
                            progressBar.setVisibility(View.GONE);
                            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);
    
        }//setImageWIthProgressBar
    
legoscia
  • 39,593
  • 22
  • 116
  • 167
Vijesh Jat
  • 131
  • 4
  • How your answer is different from https://stackoverflow.com/a/31675796/3812404? Also, point 1 is not needed. – Hari Ram May 25 '17 at 13:15
0

GlideDrawable is depreciated in 4.x version so if you are moving from 3.x to 4.x simple use Drawable :

           Glide
                .with(this)
                .load(sharedMediaUi.downloadUrl)
                .listener(object: RequestListener<Drawable> {
                    override fun onLoadFailed(
                        e: GlideException?,
                        model: Any?,
                        target: Target<Drawable>?,
                        isFirstResource: Boolean
                    ): Boolean {
                        binding.progressCircular.setVisibility(View.GONE)
                        return false
                    }

                    override fun onResourceReady(
                        resource: Drawable?,
                        model: Any?,
                        target: Target<Drawable>?,
                        dataSource: DataSource?,
                        isFirstResource: Boolean
                    ): Boolean {
                        binding.progressCircular.setVisibility(View.GONE)
                        return false
                    }
                })
                .into(binding.imgMedia)
Adnan Abdollah Zaki
  • 4,328
  • 6
  • 52
  • 58
-2

This is the best answer as it does not use any hack like setting visibility to get the desired output.

Download a gif of progressbar and call it progressbargif and put it in the drawable folder.

        Glide.with(ctx)
            .load(url)
            .thumbnail(Glide.with(ctx).load(R.drawable.progressbargif))
            .diskCacheStrategy(DiskCacheStrategy.SOURCE)
            .error(R.drawable.image_unavailable)
            .crossFade(200)
            .into(iv);

Once the url image is loaded, the thumbnail vanishes. The thumbnail vanishes immediately when the cached image is loaded.

suku
  • 10,507
  • 16
  • 75
  • 120
  • 4
    I think it was because it's not answering the question: OP already has a spinner he's happy with. It's also against Android best practices: using GIF as spinner is so 90s and increases APK size significantly; and putting a GIF into `drawable` is bad in itself because it's not loaded by the framework, it should be in `raw` or `assets` at best. There's nothing wrong with changing visibility when events happen in your app, Android is designed for that. – TWiStErRob Mar 05 '17 at 12:32
  • 1
    The user will also see an empty space while the GIF decoding happens, it's async and not immediate. You're also `RESULT`-caching the progress-bar which means it'll take a while to load. GIFs should be `SOURCE`-cached at best for efficiency; but since this is a local file, the cache needs to be `NONE` to not duplicate it on disk, consuming even more user space. – TWiStErRob Mar 05 '17 at 12:39