Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I want to show the loading progress with the image #232

Open
ximida opened this issue Nov 5, 2014 · 48 comments
Open

I want to show the loading progress with the image #232

ximida opened this issue Nov 5, 2014 · 48 comments
Labels

Comments

@ximida
Copy link

ximida commented Nov 5, 2014

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

@TWiStErRob
Copy link
Collaborator

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.

@ximida
Copy link
Author

ximida commented Nov 6, 2014

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

@hejinxigege
Copy link

I had such a similar demand,to get the progress when loading the image,please help

@sjudd
Copy link
Collaborator

sjudd commented Nov 6, 2014

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.

@alvinmap
Copy link

alvinmap commented Nov 7, 2014

Holy high!

@pavlospt
Copy link
Contributor

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

@TWiStErRob
Copy link
Collaborator

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

@Folyd
Copy link

Folyd commented Dec 25, 2014

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

@Folyd
Copy link

Folyd commented Dec 25, 2014

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().

@saket
Copy link

saket commented Dec 25, 2014

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

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

@TWiStErRob
Copy link
Collaborator

@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.

@saket
Copy link

saket commented Dec 25, 2014

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

@sjudd
Copy link
Collaborator

sjudd commented Dec 26, 2014

@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.

@fbis251
Copy link

fbis251 commented Apr 23, 2015

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

@stanbar
Copy link

stanbar commented Sep 15, 2015

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 ?

@fbis251
Copy link

fbis251 commented Sep 21, 2015

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

@kalyaganov
Copy link

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

@TWiStErRob
Copy link
Collaborator

@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 :(

@kalyaganov
Copy link

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

@hejinxigege
Copy link

@futurobot
do you know how work with volley request

@kalyaganov
Copy link

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

@slaght
Copy link

slaght commented Jan 10, 2016

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

@TWiStErRob
Copy link
Collaborator

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

demo GIF

@kalyaganov
Copy link

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

@petrovichtim
Copy link

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

@TWiStErRob
Copy link
Collaborator

TWiStErRob commented Oct 13, 2016

@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!

@petrovichtim
Copy link

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

@TWiStErRob
Copy link
Collaborator

TWiStErRob commented Oct 13, 2016

@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.

@petrovichtim
Copy link

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

@TWiStErRob
Copy link
Collaborator

@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).

@petrovichtim
Copy link

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

@TWiStErRob
Copy link
Collaborator

@petrovichtim
Copy link

petrovichtim commented Oct 13, 2016

@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

@petrovichtim
Copy link

petrovichtim commented Oct 13, 2016

  1. bug was propery progress.setIndeterminate(false);
  2. I haven't decided yet

@TWiStErRob
Copy link
Collaborator

TWiStErRob commented Oct 13, 2016

@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.

@petrovichtim
Copy link

petrovichtim commented Oct 13, 2016

@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

@ijal11
Copy link

ijal11 commented Jan 8, 2017

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

@yfsx
Copy link

yfsx commented Feb 6, 2017

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

@Johnnyne
Copy link

Johnnyne commented Jan 25, 2018

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

ezgif-2-4af73782ff

@musicode
Copy link

@TWiStErRob is Glide v4 have support this feature?

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

@TWiStErRob
Copy link
Collaborator

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.

@xiaoxxaoniao
Copy link

anything else?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests