Glide: I want to show the loading progress with the image

Created on 5 Nov 2014  路  48Comments  路  Source: bumptech/glide

Could tell me which api can get the progress when loading the image?thanks!

feature

Most helpful comment

I was playing a little with this, here's a gist.

demo GIF

All 48 comments

You know when you start the request (into: 0%) and you can set a .listener() (onResourceReady: 100%), but between that I don't think there's an option.

You can set a .placeholder() to show while the image is not ready. It's equivalent to managing what drawable is in the target between 0-99%.

If you need more granuality please explain why you want it and how would you use it.

Because when loading large image more time-consuming, want to let the user know the loading schedule

I had such a similar demand锛宼o get the progress when loading the image,please help

There isn't currently any API that would allow you to do this. You may be able to work around this by creating a custom ModelLoader/DataFetcher that would expose progress in some way.

However, even if you do so, a not insignificant portion of a load is spent decoding, transforming, and encoding images in the framework, none of which include progress APIs. As a result even if you manage to pipe through progress for the download, you won't get a particularly accurate %.

That said, you can use placeholder() and pass in an indeterminate ProgressBar to show an animated spinner during the image load, although I understand that isn't as precise as you'd like.

Holy high!

@Sjudd: How foes someone pass a ProgressBar to the placeholder() when it requires a Drawable?

Good point :) I think he meant an (animated) indeterminate progress drawable like this:
.placeholder(android.R.drawable.progress_indeterminate_horizontal)

I think just a placeholder is not enough,cloud Glide will provide such API that can get the progress when load a large image?

If i write a class named SimpleImageLoader which extends AsyncTask and use Java basic api to load large image, of course i can get progress by onProgressUpdate().

"of course i can get progress by onProgressUpdate()."

No you cannot when you're decoding Bitmap from a Uri. Try doing it.

@Saketme You can track the stream (if you acquire it first from Uri and wrap it correctly) and there's a good enough correlation of download progress and decode progress. Downloading (I/O) is the slowest, so tracking download tracks decoding. Also you can assume that by the time (or a few ms later) it is at the end of the stream the decode has finished and the bitmap is in the memory.

@Folyd an AsyncTask doesn't have much benefits, you just need a way to post progress to the UI thread (e.g. Handler with Main Looper).

Glide already has the API just not out of the box, see @sjudd's comment. The closest you can get is tracking the download by tracking/wrapping the stream and then staying at 100% or showing an indeterminate progress bar while Glide is finishing up (transforming/caching).

@sjudd please comment on this: in my mind the same way one can write a DataFetcher they can write an encoder which tracks the caching progress wrapping a real encoding stream if it's really that significant that you state. The tranformation is harder because that calls into native Android if I remember correctly which can't report back, but if progress is really that important they can reimplement it with progress. Of course some/all of the above could be hardwired into Glide depending on how much it complicates the internals... that's what this enhancement is about.

@TWiStErRob Ah I stand corrected then. Thank you :)

@TWiStErRob You can definitely track download progress from http requests by comparing where you are in the InputStream to the content length. I don't believe you can do so for arbitrary InputStreams because the InputStream API does not expose the total size of the stream. As a result we could allow DataFetchers to return progress but we couldn't enforce that all implementations do so.

Decoding, encoding, transforming, and transcoding all do not expose any way to obtain progress beyond setting some fixed % for each process. Encoding may take a substantial amount of time depending on the size of the image.

I'll consider a way to pipe progress from DataFetcher's to some interface (maybe RequestListener), but since progress only makes sense for http, isn't entirely accurate, and would be reasonably complex to implement, this isn't hugely high up on my list. If anyone here thinks this is a high priority, I'd certainly welcome a pull request.

All that said, you can definitely take our current ModelLoader APIs, implement, subclass, or fork a DataFetcher and expose progress right now without any changes in Glide. It's not trivial to do so, but it's certainly possible.

If you are using OkHTTP with Glide, you may be able to use their Progress recipe to track your download progress:

https://github.com/square/okhttp/blob/okhttp_27/samples/guide/src/main/java/com/squareup/okhttp/recipes/Progress.java

fbis251 could you please give me example how to do this ? I need to track progress while downloading image to file. Or maybe you know better solution ?

Hey, sorry it took me a while to post this but here is an example on using an okhttp progress interceptor with Glide in Android:
https://gist.github.com/fbis251/cfa169fd9e1e142e042c

@TWiStErRob why @fbis251 solution work only if i didn`t use GlideModule?

@futurobot Can't answer "it doesn't work" without having actual/expected behavior. I don't see any reason why register would stop working if you have a GlideModule: even if that module does registers itself, the code in gist should override them.

I also answered your gist question, sorry being late, I don't get no notifications for gists :(

@TWiStErRob i made little sample and it works fine with GlideModule and without it. Everything fine, thanks. example

@futurobot
do you know how work with volley request

@hejinxigege nope, i prefer OkHttp, but i think Volley requests is not much different. Volley requests

+1. Currently just using a progress spinner that spins endlessly, would be nice to have an actual progress bar

I was playing a little with this, here's a gist.

demo GIF

@TWiStErRob wow that's fantastic! Thank you ^^

@TWiStErRob I don't know what is my problem, but when glide download files it skip process updating. Seem like glide don't register network interceptor, but it does. Is it posible that glide creates different instances in one app where glide module is manifested?

@futurobot Yes if you use okhttp@aar in Gradle there'll be an automatically merged Glide module and yours, which conflict.

See https://github.com/bumptech/glide/wiki/Integration-Libraries#overriding-default-behaviour and https://github.com/bumptech/glide/wiki/Configuration#conflicting-glidemodules

@TWiStErRob any chance that my issue is because multi dex apk? I don't use proguard.

Hmm, good question, there's something in this tracker about multidex somewhere. First check your final merged manifest for multiple GlideModules. Then put breakpoints in all of those to see which one is loaded when. You should also check if the URL matches anything inside DispatchingProgressListener.LISTENERS.

@TWiStErRob well.. While building Gradle add new meta to manifest file -
<meta-data android:name="com.bumptech.glide.integration.okhttp.OkHttpGlideModule" android:value="GlideModule"/>
So i add this line into my AndroidManifest file and set attribute tools:node="remove". And that's it.
Thanks for your help :+1:

@futurobot Added a TODO to the GlideModule in the gist

@TWiStErRob Thanks for the solution. But too much code. I just need to show a circular loading progress gif file

@petrovichtim #958, #505 or just add a ProgressBar on top of your ImageView, set it visible right before the Glide load and hide in Glide listener callbacks. If you need further help, please open a new issue!

@TWiStErRob That's not what I need. I need a real loading progress

@petrovichtim I don't get it. There's no other known way of displaying progress: either use my approach to sync to progress or just an animated drawable that moves by itself. You said "I just need to show a circular loading progress gif file": by specification GIF animations are internally timed. This means you can't sync their frames with the downloaded byte count (progress). They would just play based on their internal frame delays. If you want to display the byte progress in any way (circular, horizontal, spiral, ...) you'll need to code I wrote in the gist. To only show the red circle, you still need most of the code, just remove the stuff you don't need from the layout and MyProgressTarget code.

@TWiStErRob now I get error
Error:(284, 21) error: no suitable method found for into(ProgressTarget<String,Bitmap>) method GenericRequestBuilder.<Y>into(Y) is not applicable (inferred type does not conform to upper bound(s) inferred: ProgressTarget<String,Bitmap> upper bound(s): Target<GlideDrawable>) method GenericRequestBuilder.into(ImageView) is not applicable (argument mismatch; ProgressTarget<String,Bitmap> cannot be converted to ImageView) method DrawableRequestBuilder.into(ImageView) is not applicable (argument mismatch; ProgressTarget<String,Bitmap> cannot be converted to ImageView) where Y is a type-variable: Y extends Target<GlideDrawable> declared in method <Y>into(Y)
My bind method is
https://gist.github.com/anonymous/ccef4ceff58275fcb51b70b8f2074207
Studio dont like this line

.into(target)

@petrovichtim It says what the problem is, it needs Target<GlideDrawable> and you're giving it Target<Bitmap>: either add asBitmap() like in the gist or declare target with the correct generics (you'll need to replace the constructor argument with GlideDrawableImageViewTarget).

@TWiStErRob Thanks, but I do not understand where I need to change constructor argumen. Can you write some code please?

@TWiStErRob Thanks , I change my code to this
Now I faced strange bugs:

  1. progressBar firstly horizontal and later become a circular
    Like on image
    screenshot_20161014-000813
  2. thumbnail Request hide the progress bar
  1. bug was propery progress.setIndeterminate(false);
  2. I haven't decided yet

@petrovichtim
re circle VS line: check you drawable andsetIndeterminate.
re 2.: thumbnails are not part of the gist. The gist is a proof of concept, which is not a production ready "just copy-paste and happy" code. It's a concept you can build on.
re this whole conversation: the gist I provided is a workaround for a feature that potentially needn't be part of Glide. Glide is an image loading library and what you're trying to do is a job of a networking library. This is why I needed to use OkHttp to be able to make the workaround.

If you continue down this path you'll face hard problems. If it was easy it would probably already be part of Glide.

@TWiStErRob I think you can first download the thumbnails and then start the main download. But it will be a complex code based on the events of the first download .
In the end I did this
20161014_0150391111

Can I dismiss progress dialog when all the images that I request from the server is finished
My problem when the request is complete then the progress bar already dismiss before all the finished images on request (I'm using volley)
thanks

it can't be done on gilde listener? it should be good when it can be done on something like this

Glide.with(activity).load(imageUrl).asGif().listener(new RequestListener<String, GifDrawable>() {
                   //new function maybe
                   @Override
                    public boolean onDownload(Progress currentProgress) {
                        return false;
                    }

                    @Override
                    public boolean onException(Exception e, String model, Target<GifDrawable> target, boolean isFirstResource) {
                        return false;
                    }

                    @Override
                    public boolean onResourceReady(GifDrawable resource, String model, Target<GifDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
                        tv_progress.setVisibility(View.GONE);
                        progressWheel.setVisibility(View.GONE);
                        return false;
                    }
            }).into(gifImageView);`

I wrote the simple tutorial to explain how to integrate YOUR loading progress view with Glide V4.

ezgif-2-4af73782ff

@TWiStErRob is Glide v4 have support this feature?

I don't want to add okhttp for a simple app.

It's likely not the question of Glide supporting it, it's the question of Java's built-in HttpURLConnection not providing any API to do this. OkHttp has a nice progress API, that's why I did it with that. I guess you could write a custom fetcher (see HttpUrlFetcher) that somehow integrates and publishes progress similar to how I did with OkHttp by using the Content-Length + wrapping the stream that knows how far it's downloaded.

anything else?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

PatrickMA picture PatrickMA  路  3Comments

sergeyfitis picture sergeyfitis  路  3Comments

AndroidJohnsonWang picture AndroidJohnsonWang  路  3Comments

StefMa picture StefMa  路  3Comments

billy2271 picture billy2271  路  3Comments