I want to load and cache images only in memory and not pass them to a view and later on when I need them to be loaded on the UI to get them from memory cache if they existed in memory.
I tried:
Glide.with().load(uri).into(new SimpleTarget<GlideDrawable>(WIDTH,HEIGHT)
{
#Override
public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
//left empty
}
}
);
But when later on I make the call to load that uri in an ImageView it will still load it from the path and not memory.
Is there another way to have images cached in memory without loading them on the UI?
Documentation on how to cache images on background thread can be found here.
Here is some example code from the page showing how a file would be downloaded to cache, without displaying the image in the UI:
FutureTarget<File> future = Glide.with(applicationContext)
.load(yourUrl)
.downloadOnly(500, 500);
// Can be omitted if you only want to have the data cached (same goes for the "future" instance variable
File cacheFile = future.get();
However, make sure you have configured Glide such that caching is enabled: https://github.com/bumptech/glide/wiki/Configuration
Actually I found the preload method in API for this exact purpose:
preload API change log
Related
I want to display one image into two different image views using glide.I know that i can simply use the code below to do it.
ImageView imageView = findViewById(R.id.header_image);
Glide.with(this).load(R.drawable.header_image).into(imageView);
ImageView imageView2 = findViewById(R.id.header_image);
Glide.with(this).load(R.drawable.header_image).into(imageView2);
But it requires to load the same image twice into memory and i don't want that due to memory issues.I want to load the image once and diaplay it into two image views.What can i do to achieve it?
You no need to worry about memory issue while using glide because glide has own caching system to optimize memory pls read this doc
Glide provides a number of options that allow you to choose how loads will interact with Glide’s caches on a per request basis.
Disk Cache Strategies
DiskCacheStrategy can be applied with the diskCacheStrategy method to an individual request. The available strategies allow you to prevent your load from using or writing to the disk cache or choose to cache only the unmodified original data backing your load, only the transformed thumbnail produced by your load, or both.
The default strategy, AUTOMATIC, tries to use the optimal strategy for local and remote images. AUTOMATIC will store only the unmodified data backing your load when you’re loading remote data (like from URLs) because downloading remote data is expensive compared to resizing data already on disk. For local data AUTOMATIC will store the transformed thumbnail only because retrieving the original data is cheap if you need to generate a second thumbnail size or type.
To apply a DiskCacheStrategy:
GlideApp.with(fragment)
.load(url)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(imageView);
Loading only from cache
In some circumstances you may want a load to fail if an image is not already in cache. To do so, you can use the onlyRetrieveFromCache method on a per request basis:
GlideApp.with(fragment)
.load(url)
.onlyRetrieveFromCache(true)
.into(imageView);
If the image is found in the memory cache or in the disk cache, it will be loaded. Otherwise, if this option is set to true, the load will fail.
You can use following code to load an image once and display it in multiple imageviews.
Glide.with(this)
.asBitmap()
.load(R.drawable.header_image)
.into(new SimpleTarget<Bitmap>() {
#Override
public void onResourceReady(#NonNull Bitmap resource, #Nullable Transition<? super Bitmap> transition) {
imageview.setImageBitmap(resource);
imageview2.setImageBitmap(resource);
}
});
If you are using latest version of Glide then create RequestOptions like
private RequestOptions simpleOptions = new RequestOptions()
.centerCrop()
.placeholder(R.color.color_gray)
.error(R.color.color_gray)
.diskCacheStrategy(DiskCacheStrategy.RESOURCE);
Use RequestOptions to load image with set properties
Glide.with(context)
.load(url)
.apply(simpleOptions)
.into(imageView);
Or maybe this way…
RequestBuilder<Drawable> builder = Glide.with(this).load(drawableResId);
builder.into(imageView0)
builder.into(imageView1)
try this way ...
setImage(R.drawable.header_image,imageView ,imageView2 );
void setImage(int image, ImageView... imageView) {
for (ImageView imageView : imageView) {
if (imageView != null) {
Glide.with(this).load(image).into(imageView);
}
}
}
Scenario:
I have a large GIF image which I want to cache the first time user opens the app using Glide - Image Loading and Caching library. After that whenever user opens the app, I want to show the cached version if present. This GIF URL will expire after a given interval. When it expires, I fetch the new GIF URL and display/cache that for future use.
What I tried:
I went through Caching and Cache Invalidation on Glide's github page. I also went though the Google Group thread Ensuring That Images Loaded Only Come From Disk Cache, which shows how to get the image form cache. I also went through How to invalidate Glide cache for some specific images question.
From the links above I see the following code sniplet which shows how to load the image from cache. However this only tries to get the image from cache. If its not present in cache, it doesn't try to get from the network and fails:
Glide.with(TheActivity.this)
.using(new StreamModelLoader<String>() {
#Override
public DataFetcher<InputStream> getResourceFetcher(final String model, int i, int i1) {
return new DataFetcher<InputStream>() {
#Override
public InputStream loadData(Priority priority) throws Exception {
throw new IOException();
}
#Override
public void cleanup() {
}
#Override
public String getId() {
return model;
}
#Override
public void cancel() {
}
};
}
})
.load("http://sampleurl.com/sample.gif")
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.into(theImageView);
Questions:
Is there a cleaner way to achieve the following: Show the GIF image from the cache if present else download the GIF, cache it for later use and show it in the ImageView.
The caching article above mentions the following:
In practice, the best way to invalidate a cache file is to change
your identifier when the content changes (url, uri, file path etc)
The server sends a different URL to the app when the previous one expires. In this case, I believe the old image will eventually be Garbage Collected? Is there a way to force remove the image from the cache?
On a similar note, is there a way to prevent the Garbage Collection of an image with specific key (to prevent downloading the large file again) and then later instruct to delete the old image from cache when the URL changes?
You don't need a custom ModelLoader to show the GIF from cache if present and fetch it otherwise, that's actually Glide's default behavior. Just using a standard load line should work fine:
Glide.with(TheActivity.this)
.load("http://sampleurl.com/sample.gif")
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.into(theImageView);
Your code will prevent Glide from downloading the GIF and will only show the GIF if it is already cached, which it sounds like you don't want.
Yes, the old image will eventually be removed. By default Glide uses an LRU cache, so when the cache is full, the least recently used image will be removed. You can easily customize the size of the cache to help this along if you want. See the Configuration wiki page for how to change the cache size.
Unfortunately there isn't any way to influence the contents of the cache directly. You cannot either remove an item explicitly, or force one to be kept. In practice with an appropriate disk cache size you usually don't need to worry about doing either. If you display your image often enough, it won't be evicted. If you try to cache additional items and run out of space in the cache, older items will be evicted automatically to make space.
Glide.with(context)
.load("http://sampleurl.com/sample.gif")
.skipMemoryCache(true)
.into(imageView);
You already noticed that we called .skipMemoryCache(true) to specifically tell Glide to skip the memory cache. This means that Glide will not put the image in the memory cache. It's important to understand, that this only affects the memory cache! Glide will still utilize the disk cache to avoid another network request for the next request to the same image URL.for more read this
Glide Cache & request optimization.
Happy coding!!
I have an app that loads images on each item on a list view, and I use Volley to make life easier for me; I need to have to images loaded from disk if it's already been downloaded before.
Problem: It won't work. It needs to re-download the images all over again. I need to have the image saved even after I exit the app.
Weird: It works only on one particular image (and it has nothing to do with size)!
What I Used: I patterned this using this site: https://github.com/rdrobinson3/VolleyImageCacheExample.
I also tried this: http://howrobotswork.wordpress.com/2013/06/02/downloading-a-bitmap-asynchronously-with-volley-example/
The Code:
String godzilla = "http://vineland.pynchonwiki.com/wiki/images/c/cf/Godzilla.jpg";
//String meme = "http://upload.wikimedia.org/wikipedia/en/d/d7/Meme_Many_Journeys.jpg";
ImageCacheManager.getInstance().getImageLoader().get(godzilla, new ImageLoader.ImageListener() {
#Override
public void onResponse(ImageLoader.ImageContainer imageContainer, boolean b) {
viewHolder.backgroundImage = imageContainer.getBitmap();
updateBackgroundImage(viewHolder, viewHolder.backgroundImage, object);
updateLayoutAlignmentParams(viewHolder);
}
#Override
public void onErrorResponse(VolleyError volleyError) {
}
});
if(viewHolder.backgroundImage != null)
updateBackgroundImage(viewHolder, viewHolder.backgroundImage, object);
I've tried the meme website, and it still has problems. I had one particular site that contains an image that oddly works. Which makes it even more confusing.
Edit: Additional info, it seems like there's an error on adding lruEntries as lruEntries.remove(entry.key is being called on completeEdit().
Volley has 2 cache layers when it comes to images:
The L1 level: a memory cache provided by you in the ImageLoader constructor.
The L2 level: a disk cache that is shared among every request performed by the same RequestQueue.
The disk cache caches every response unless explicitly requested not to by the request. But, the caching is performed according to the HTTP cache headers of the response.
When you request an image, this is what Volley does:
Check L1 cache for image. Return if found.
Image not in memory - Check L2 cache. If found check expiration of the cache headers. If still valid, add to L1 cache and return image.
Image not on disk (either not there or expired) - Perform a network request. Cache the response in the disk cache and the bitmap in the memory cache and return.
I bet that the image that loaded from the disk has cache headers.
IMO, you have 3 options:
The image server is yours - add the appropriate cache headers.
The image server isn't yours - accept the fact the some images will not be cached on the disk.
Override the caching policy to better suit your needs. This means editing the Volley source code.
The library only exposed option to enable/disable caching in display options. Is there a way to avoid disc or memory cache check when loading images?
My problem is that the library always check the disc cache first. My disc cache is set with small thumbnail size. When I need to load images for screen size, I cannot skip the disc cache , it always get me the lower resolution image.
UIL always check caches before displaying. So there is no way to avoid without changins the sources.
But I think you can solve your problem by extending disk cache. The goal is to return non-existing file from get() method when you want to load full-sized image.
So you should do as usual to load thumbnails. When you need to display full-sized image you should disable caching on disk in display options (DisplayImageOptions) and then do something like this:
((MyDiscCache) imageLoader.getDiscCache()).setIgnoreDiskCache(true);
So your cache must return any non-existing file (but not null).
When you return to display thumbnails you should "enable" (setIgnoreDiskCache(false)) disk cache back.
UPD:
Create your own disk cache and set it to config.
public class MyDiscCache extends UnlimitedDiscCache {
private boolean ignoreDiskCache;
public MyDiscCache(File cacheDir) {
super(cacheDir);
}
public MyDiscCache(File cacheDir, FileNameGenerator fileNameGenerator) {
super(cacheDir, fileNameGenerator);
}
#Override
public File get(String key) {
if (ignoreDiskCache) {
return new File("fakePath");
} else {
return super.get(key);
}
}
public void setIgnoreDiskCache(boolean ignoreDiskCache) {
this.ignoreDiskCache = ignoreDiskCache;
}
}
Care: No code here, only text and some questions about bitmap caching
I'm currently developing an App which is almost finished. The only thing left, that I would like to do is caching images. Because, at the moment, when the user opens the app the app downloads images from a server. Those images are not static, that means they can change every minute/hour/day. I don't know when they change, because it's a list of images gathered by the amount of twitter shares, facebook likes etc. That means, when a picture has 100 likes and 100 tweets it is place 1. But when another picture gets more likes and tweets it gets rank 1 and the other one will be placed as rank 2. This isn't exactly my app, but just so you understand the principle.
Now I looked into Bitmap caching so the user doesn't have to download the same images over and over. The question I do have is how do I do it? I mean, i Understand HOW to cache bitmaps.
I looked into this documentation article: http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html
But, the problem is, how do I know if the Bitmap already got downloaded and has been cached or if I have to download it again? Don't I have to download the image first to check if I have this particular image already in my system?
I thought about getting the URL of the image, then convert it into a hash. And then, save the files to the cache with the hash as filename. Then, when the image URL comes it will be checked wether the image is available in the cache or not. If it is it will be loaded if not it will be downloaded. Would that the way to go be?
Or am I misunderstanding bitmap caching and it does it from its own already?
my best advice on those cases is: Do not try to re-invent the wheel.
Image loading/caching is a very complex task in Android and a lot of good developers already did that. Just re-use their work.
My personal preference is Picasso http://square.github.io/picasso/
to load stuff with it is one very simple line of code:
Picasso.with(context).load(url).into(imgView);
it's that simple!
It does both RAM and disk cache, handles all threading issues and use the excellent network layer okHttp.
edit:
and to get access directly to the Bitmap you can:
Picasso.with(context).load(url).into(new Target() {
void onBitmapLoaded(Bitmap bitmap, LoadedFrom from){
// this will be called on the UI thread after load finishes
}
void onBitmapFailed(Drawable errorDrawable){
}
void onPrepareLoad(Drawable placeHolderDrawable){
}
});
Check this library:
http://code.google.com/p/android-query/wiki/ImageLoading
It does caching automagically
example
//fetch a remote resource in raw bitmap
String url = "http://www.vikispot.com/z/images/vikispot/android-w.png";
aq.ajax(url, Bitmap.class, new AjaxCallback<Bitmap>() {
#Override
public void callback(String url, Bitmap object, AjaxStatus status) {
}
});.
http://code.google.com/p/android-query/wiki/AsyncAPI
You can try https://github.com/thest1/LazyList
the project code was designed for listviews, but still, its purpose is to download images from URLs in the backgroud so the user doesn't have to hold on the whole downloading time.
you take these JAVA classes : FileCache, ImageLoader, MemoryCache, import them into your project,
for downloading an image you just call imageLoader.DisplayImage(URL,ImageView);
the best part is that it takes care of the cache itself so you don't have to worry about that
hope this helps