I'm maintaining an android app that uses Glide to download images.
Besides images, sometimes it also displays videos, and uses the same process to display the video thumbnail.
I noticed in this cases, Glide correctly extracts and displays a thumb, BUT it always downloads the entire video do do that, which is not convenient.
My question is: Is it possible to make Glide stop downloading after reading the first frame? Or Glide is not recommended for this job?
This is a test code.
I also tried adding .frame(30_000_000L) in the requireOptions.
btn.setOnClickListener{
// a local server just for testing
val url = "http://192.168.1.6:5676/roxo.mov"
Glide.with(this)
.asBitmap()
.load(url)
.apply(RequestOptions().diskCacheStrategy(DiskCacheStrategy.ALL))
.override(200, 200)
.into(img_view)
}
Related
Hi I am using Glide to load image and after following many posts I tried to implement Glide caching using
RequestOptions().diskCacheStrategy(DiskCacheStrategy.ALL).centerCrop()
Glide.with(mContext)
.load(imageUrl)
.transition(ImageUtil.crossFadeTransition())
.apply(ImageUtil.requestOptionsForSlider())
.listener(glideRequestListner)
.into(imageView)
My knowledge is that if I use diskCacheStrategy(DiskCacheStrategy.ALL) then the above Glide image loading code will automatically use cache if available, or download if not, right?
But I see everytime the code is called, (checking my internet speed meter) that it is always fetching/downloading from the given url (even though I can see the app memory size is increasing).
I even tried this code also-
val future: FutureTarget<File> = Glide.with(mContext)
.load(imageUrl)
.downloadOnly(500, 500)
Nothing seems to work
What should I do so that Glide uses cache if available?What is wrong with my conception about the caching implementation? Any help is very much appreciated!
Are you sure it is downloading again ? did you try disabling internet just before loading the images ?
Otherwise, is your image URL always the same for the same image ? (as Glide uses it as a cache key).
You can use this in the following calls to check if images are in cache:
Glide.with(fragment)
.load(url)
.onlyRetrieveFromCache(true)
.into(imageView);
I am trying to make a recyclerview with gifs. Everything shows perfectly but fresco do not cache gifs. After scroll recycler down and scroll up again, gifs are loading once again. I supposed they should be cached and loaded a bit quicker. Previously I used ION library. Loading was quicker and did not have cache problem. I had to change lib because, it has some problem with gif decoding, described here. Current solution looks like that:
//for default initial in application class
Fresco.initialize(this);
//I have also tried to change DiskCacheConfig and ImagePipelineConfig params.
//Without any positive result
//for recyclerview on onBindViewHolder
GenericDraweeHierarchy hierarchy = holder.draweeView.getHierarchy();
Uri uri = Uri.parse(path);
hierarchy.setPlaceholderImage(R.drawable.img_bg);
Logger.e(check(uri) + " " + uri.toString());
DraweeController controller = Fresco.newDraweeControllerBuilder().setUri(uri)
.setAutoPlayAnimations(true).build();
holder.draweeView.setController(controller);
//for method which show cached uri images in imagepipeline
public static boolean check(Uri uri) {
ImagePipeline imagePipeline = Fresco.getImagePipeline();
return imagePipeline.isInBitmapMemoryCache(uri);
}
//... all the time log shows "false + gif url"
I have not seen any information about not caching animated images. There is information about not supported image postprocessing for animations, but it's everything about that. How to correctly cache gifs?
edit:
It looks like fresco cache animations, because below method return true for reloaded gifs.
public static boolean isImageDownloaded(Uri loadUri) {
if (loadUri == null) {
return false;
}
CacheKey cacheKey = DefaultCacheKeyFactory.getInstance()
.getEncodedCacheKey(ImageRequest.fromUri(loadUri));
return ImagePipelineFactory.getInstance().getMainDiskStorageCache().hasKey(cacheKey)
|| ImagePipelineFactory.getInstance().getSmallImageDiskStorageCache()
.hasKey(cacheKey);
}
Just to make things a bit more clear, Fresco has 3 levels of cache:
DiskCache - Keeps image files in their original format. (To be
precise, if on an Android version that doesn't fully support webp
images, they may be transcoded to other format before storing.)
EncodedMemoryCache - In-memory cache of images in their original encoded format. (Image is kept as a byte-array of the original bytes
as they are stored on disk + some additional metadata.)
BitmapMemoryCache - In-memory cache consisting mostly of Android Bitmaps. Bitmaps are decoded images and each pixel occupies 32bits
which is significantly more than what it takes when encoded.
The trade-off is obviously space vs time. Available memory is limited and if the image is not in the bitmap cache, it will have to be decoded again. Furthermore, if it is not in the encoded memory cache either, it will have to be read from the disk which also can be slow.
Now back to the animated images. This is a known limitation. Animated images are not cached in their decoded form because that would exhaust the bitmap cache (just multiply the num_frames * width * height * 32bpp) and a single animated image can possibly evict every other image in the cache. Instead they are decoded on demand and only a couple of frames that are about to be displayed next are kept in a short-lived cache.
We have some plans to improve animations, although I cannot provide any time estimates.
I was facing the same issue, it appears that Fresco is correctly caching the gif images, but in fact it's taking time to decode and play the animation each time you scroll through the RecyclerView or any other view you're using.
However if you use a gif image without animation, the gif image doesn't "reload" when scrolling through the view.
Since I have control over the images displayed inside my app. I am creating 2 versions of the gif images on my server, the first without animation to display inside the RecyclerView/ListView and the other to display inside the "Media viewer" activity, when the user clicks on an item in the list.
Fresco, they mainly focused low size gifs. I tried with low size gifs in recycleview, caching working perfectly. If you use high resolution gifs, they need high memory consumption for decode and caching. may be surpass heap size. so they are decoded on demand, and only a couple of frames (those about to be displayed) get cached.
It is possible to configure fresco to display the first frame as soon as it is available (without decode whole frame) and cache the static first frame easily.
ImageDecodeOptionsBuilder b = new ImageDecodeOptionsBuilder();
b.setForceStaticImage(true);
ImageDecodeOptions imageDecodeOptions=new ImageDecodeOptions(b);
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(animatedGifUri).setImageDecodeOptions(imageDecodeOptions).setLocalThumbnailPreviewsEnabled(true).build();
I am using Picasso to handle image loading and caching in my Android Udacity project and I am noticing the caching is not working as I'd expect:
As you can see on the left fragment, the image has already loaded in an earlier thread. Now, with the same URL link, I am asking Picasso to place that image in the fragment on the right.
Here is the code which generates the grid view on the left fragment (and occurs first):
https://github.com/esend7881/udacity-android-popmovie/blob/a9a1b9a19a37594bb5edd736b7ec59229fb5905a/app/src/main/java/com/ericsender/android_nanodegree/popmovie/adapters/GridViewAdapter.java#L71
String load = String.format(sImgUrl, sImgSize, movie.poster_path);
Picasso.with(mContext.getApplicationContext())
.load(load)
.placeholder(R.drawable.abc_btn_rating_star_on_mtrl_alpha)
.error(R.drawable.abc_btn_rating_star_off_mtrl_alpha)
.resize(550, 775)
.into(viewHolder.imageView);
And then here is the code which runs in the right fragment:
https://github.com/esend7881/udacity-android-popmovie/blob/a9a1b9a19a37594bb5edd736b7ec59229fb5905a/app/src/main/java/com/ericsender/android_nanodegree/popmovie/fragments/MovieDetailsFragment.java#L308
Picasso.with(getActivity().getApplicationContext())
.load(String.format(sImgUrl, sImgSize, mMovieObj.poster_path))
.error(R.drawable.blank)
.fit()// .resize(366, 516)
.into(mMovieThumb, new com.squareup.picasso.Callback() {
#Override
public void onSuccess() {
Utils.log(sw.toString());
Utils.hideViewSafe(mMovieThumbProgress);
}
#Override
public void onError() {
Utils.log(sw.toString());
Utils.hideViewSafe(mMovieThumbProgress);
}
});
I am using the same application context in each as well as the load text:
String.format(sImgUrl, sImgSize, mMovieObj.poster_path))
and
getActivity().getApplicationContext()
So, I would think Picasso ought to detect when the exact same URL load link appears in the same context within a short period of time from each other and Picasso would then load the exact same image back into the app.
If this is not how Picasso caching works, then how does it?
As a comment mentioned, I'd guess this is affected by the size of the image being different in both fragments.
I'd recommend using https://github.com/facebook/fresco instead of picasso. It's more efficient, especially with different sizes. You can also directly access cached files if required https://github.com/facebook/fresco/issues/80
It's probably related to the HTTP headers received when getting the image that do not allow caching, as Picasso relies on an HTTP component to do the caching.
Try uploading your image on imgur, try hardcoding that path and see if it works. If that's the case, you'll have to find a workaround on how to get the image from the movie database.
I'm using picasso library to download images from URL.What I need is just download the stream not a bitmap, but there is no such method in it.Is it true?
There is :
Picasso.with(this).load(URL_LONG).get(); // return bitmap
Sometimes there are some large images from URL.I need to handle them before displaying for avoiding out of memory.So I cannot load them into bitmap immediately.This is the reason i need the stream.
There is already a feature to provide what you need in Picasso Library. You can actually scale the image when you stream it. Check out this SOF Question.
I have trouble when I'm using Glide in my app. As I've understood, if image was downloaded once and I request image from cache from other activity, Glide must show image quick. And I got this behavior, but not in my app. Image loads very slow (about 3 seconds), although in another app it was about 0.4 second.
My code with calling Glide:
Glide.with(this)
.load(url)
.signature(new StringSignature(url))
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(mHeader);
And in other activity code are same.
May you help me?
Thanks
You don't need the signature(url) part, the model (url String in your case) is already a part of the cache key.
The problem may be that your header changes size. The view size (= resulting Bitmap size) needs to be constant for a cache hit. However since you're doing ALL caching the load should still be fast. Is there anything changing in the url maybe, like a sessionid or similar? That would make the cache miss.
If the url you're loading is an animated GIF RESULT caching can be the culprit, here's a reference.