I am using Glide in my Android application for loading images from internet. I've disabled memoryCache when loading images but diskCache is still active and it uses default strategy to cache resources on the disk. My question is What Glide do during caching resources on the disk storage if disk's storage is full and there isn't any free space on it? Will it throw and exception or what?
No it wont throw any errors. but it might give a callback in
#Override
public void onLoadFailed(Exception e, Drawable errorDrawable) {
super.onLoadFailed(e, errorDrawable);
}
Currently Glide downloads the whole image and decodes it. Then fails to write the cache and error is displayed. Next time it tries it'll download it again, and do the same thing. If this proposal is implemented it would fail at writing cache, but since it displays the image next time it MAY hit the cache and prevent downloading again. So this fix would save bandwidth and enhance UX. because of this Glide may not load images when device space run out.
Hope this answers to your question
Related
This question already has answers here:
Android:java.lang.OutOfMemoryError: Failed to allocate a 23970828 byte allocation with 2097152 free bytes and 2MB until OOM
(31 answers)
Closed 3 years ago.
I have a RecyclerView in an android app. I am doing some kind of file explorer.
When I plug my own device on the computer, it runs out of memory when I reach the Camera folder in DCIM folder.
This is because there are a lot of pictures in there and I am trying to show them as the ImageView instead of the usual file icon drawable.
When the images are loaded the app runs out of space so it crashes
I implemented the app using a RecyclerView thinking it is going to recycle the views and not run out of memory or lag. But it doesn't seem to work.
I tried doing some kind of workaround by loading images only for the visible portion of the RecyclerView but it requires a lot of twists and it didn't work in the end.
Is there a way to load lot of images and make sure they don't take too much space in RAM. I'm using an old phone and I'd like my app to work on it. It is a Galaxy Ace II.
use glide
add com.github.bumptech.glide:glide:4.10.0 in your dependencies
Why handling images in the app, using Glide or Picasso is stronly recommended.
1- To implement Glide https://github.com/bumptech/glide (that I prefer)
2- To implement Picasso https://square.github.io/picasso/#download (also a strong library)
They handle images professionally. They have tools to avoid OOM caused by images. you should follow tutorials to implement and use them.
But OOM is not only because of the images. Whole application must be observed.
https://stackoverflow.com/a/58358334/11982611 this post can help for this.
After implmenting, To make resizing with Glide
Glide.with(mCtxt).load( image uri or url or drawable )
.error( image when error occurs )
.override(320,180) // overrided width and height
.centerCrop()
.into( imageview );
Whatever you are using, you should adjust your images according to mobile device
Thank you for your answers.
I ended up doing the following:
Bitmap bitmap = BitmapFactory.decodeFile(filePath);
bitmap = Bitmap.createScaledBitmap(bitmap, 50, 50, false);
imageView.setImageBitmap(bitmap);
It is still very laggy even at 50x50 pixels. I may try GLIDE library.
I have a link of an image in my code, which will be updated in server some times.
I load this image with Picasso library and I have two problems.
I want to show the updated image when it is changed in server and cache it again in Picasso.
First, the invalidate() method of Picasso does not invalidate disk cache memory (network cache) and the cached image in disk still show.
Second, for the first problem there are some answers in Stackoverflow such as this one: Abort memory cache and disk cache, The problem with this :it will not cache again the new image because of the policies, but I want to cache again the new image.
My app is connected to a server which I can tell the app whenever an image is changed, but the URL of images does not change.
What should I do?
I'm using Picasso in my application for loading image efficiently and is doing his job at the best.The issue is that, currently if i call Picasso.with() multiple times with same url, however each time with an image view having different dimensions, the image gets downloaded again.In Glide we have the methods .diskCacheStrategy() with DiskCacheStrategy.SOURCE for resolving the problem.is there any alternative way in Picasso ?
In this query we will get the solution for Glid but not for Picasso.how can i reuse the image without redownloading for different dimensions ImageView.
This is the code I'm using
Picasso.with(context)
.load(URI)
.placeholder(R.drawable.ic_profile_thumb)
.resize(180, 180).centerInside()
.into(viewHolder.imgThumbnail);
Picasso does not cache the image to disk, Picasso only has a memory cache. the Disk cache is done by the networking library(OKhttp). so the image written to the disk cache is never re-sized.
if the same url image is downloaded multiple time you might have to check your networking library.
If your project is using the okhttp library then picasso will automatically use it as the default downloader. If you are are using any other network library then you will have to write your own downloader and set it using
Picasso.Builder(context).downloader(customDownloader)
this link might make things clear
Picasso by default doesn't resize images. If you do a simple call like the next one...
Picasso.with(context).load("https://goo.gl/v9EkbF").into(imageView);
...Picasso is caching the full-size image. From that moment, every time you call the same URL, Picasso will reuse that full-size image and let the GPU do the resizing into the view.
Use the resize() method you are only caching the resized image, and Picasso will need to download the image again if you use a different size.
Don't use the resize() option and you'll get better bandwidth usage, but be careful with memory usage.
The defaults in Picasso
Picasso does have automatic memory and disk caching. Any image that was requested recently will be in memory cache. If it isn't there Picasso will check the disk cache. If it's not available on disk, only then Picasso will start the network request.
All requested images are stored in both caches until they have to be deleted in order to free space.
The default's in 2.5.2 are:
LRU memory cache of 15% the available application RAM
Disk cache of 2% storage space up to 50MB but no less than 5MB.
Picasso will use OkHttp as the Http client if it's included as a Gradle dependency. Otherwise Picasso will fall back to HttpUrlConnection.
You can increase the disk cache like this (example for 100MB):
Picasso picasso = new Picasso
.Builder(this)
.downloader(new OkHttpDownloader(getCacheDir(), 100000000))
.build();
Picasso.setSingletonInstance(picasso);
Changing the disc cache size does not change the cache policy.
Memory Policies
MemoryPolicy.NO_CACHE: The image won't be served from memory. This one doesn't avoid to serve images from disk. To avoid disk look down on Network Policies.
MemoryPolicy.NO_STORE: The image won't be stored in memory. Use this for images that will be loaded only once.
Example
Picasso
.with(context)
.load(https://goo.gl/v9EkbF)
.memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE)
.into(imageView);
Network Policies
NetworkPolicy.NO_CACHE: The image won't be served from disk cache.
NetworkPolicy.OFFLINE: The image will (if possible) be served just from cache (memory or disk) but never from network.
Example:
Picasso
.with(context)
.load(https://goo.gl/v9EkbF)
.networkPolicy(NetworkPolicy.NO_CACHE)
.into(imageView);
Memory and caching considerations
Glide uses by default RGB565 and cache a image resized into the
memory.
Picasso uses by default RGB888 and cache the full size image into the
memory and let GPU does the real-time resizing when drawn.
RGB565 is half the size of RGB888. The result of using RGB565 and smaller images is that Picasso memory footprint is higher (might be 3x/4x) than Glide's.
Those are just the defaults. Glide can be configured to use RGB888 and Picasso to use RGB565. Picasso can be configured to throw into memory just the resized images like Glide.
Under the same setups, the memory footprint is almost the same.
Bandwidth considerations
Glide caches separate file for each size. If you load another size of
the same image, it will be downloaded again before, resized and then
cached.
Picasso takes always the full-size image from cache and then let the GPU make the resizing into the view.
You can ask Glide to cache everything, full-size image and resized images but by default Glide's bandwidth consumption is higher.
Note
Picasso 2.6 is coming and I have no idea about what's different/new.
Sources
Picasso
Introduction to Glide, Image Loader Library for Android, recommended
by Google
What is default cache policy?
Picasso — Influencing Image Caching
You can use OkHttp from the same vendor "SquareUp".
This answer show you how to do it with details.
UPDATE: The links were old, by the way, Here are the changes in the newest versions:
https://github.com/square/picasso/blob/master/CHANGELOG.md
And as #Sotti said, Picasso has Automatic memory and disk caching which they mentioned about that in the Introduction section:(the last part)**
http://square.github.io/picasso/#introduction
In this query we will get the solution for Glid but not for
Picasso.how can i reuse the image without redownloading for different
dimensions ImageView.
Actually, Picasso only has a memory cache, But you may want to use OkHttp for that.
Check this link: https://stackoverflow.com/a/18552559/4409113 Which says:
If you are referring about the disk cache, then no Picasso does not
support that at the moment. This is by design because the disk layer
cache is done by the HTTP layer and makes no distinction about it.
Check this out too: https://corner.squareup.com/2013/05/picasso-one-dot-oh.html
Picasso automatically utilizes a memory and disk cache (provided by
the HTTP client) to speed up bitmap loading. For development you can
enable the display of a colored marker which indicates the image
source.
And also, check this question: How to implement my own disk cache with picasso library - Android?
To save the files in custom cache directory using OkHttp:
OkHttpClient okHttpClient = new OkHttpClient();
File customCacheDirectory = new File(Environment.getExternalStorageDirectory().getAbsoluteFile() + "/MyCache");
okHttpClient.setCache(new Cache(customCacheDirectory, Integer.MAX_VALUE));
OkHttpDownloader okHttpDownloader = new OkHttpDownloader(okHttpClient);
Picasso picasso = new Picasso.Builder(mainActivity).downloader(okHttpDownloader).build();
picasso.load(imageURL).into(viewHolder.image);
From: https://stackoverflow.com/a/33276054/4409113
As you can see, uses setCache.
If not what is a good way to cache images locally?
-- Note: I am coding for Android.
Picasso.
Many common pitfalls of image loading on Android are handled
automatically by Picasso:
Handling ImageView recycling and download cancelation in an adapter.
Complex image transformations with minimal memory use.
Automatic memory and disk caching.
When you want to send the image to your cloud, you could use ParseFile in conjunction with Picasso, get the bytes from the image and save() or saveInBackground().
My app shows images to user one after one. The images are downloaded from server. As I do not want the user to wait for the images to be downloaded I cached those in a local file system (say new 50 images) .
Implementation:
from onCreate method start a AsyncTask that will keep in downloading images in background.
Is AsyncTask best for this use case?I do not want to use a Service as I do not want the download to happen continuously
Is AsyncTask best for this purpose?
I would suggest using an existing library, such as Picasso (by Square) or Volley (by Google).
Picasso is especially easy to implement and will work excellently for your purpose, and is as easy as:
Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
You won't have to concern yourself with AsyncTasks or AsyncTaskLoaders as the library takes all of this out of your hands, caching both images in memory and on the disk.
If you insist on building your own solution, I suggest looking around for related questions as there are many things to bear in mind:
AsyncTasks may be ill fitted as they are directly coupled with a single activity; you'll need a Loader or a mechanism similar to Loaders to deliver results to whichever activity wants an image.
On older devices, bitmaps reside in a special region of memory that isn't managed by the GC; you'll have to dispose of bitmaps manually when you're done with them.
Bitmaps use a significant amount of memory and need to be carefully managed to avoid OOMEs, such as downsampling them when loading and storing in memory inside an LruCache.
Beware of managing the size of the image cache directory when writing images to disk.
Yes, you can use Asynctask for this purpose. And using one of the apis of Asynctask "onProgressUpdate(), you can in parallel update the UI as your images are getting downloaded.
you can use universalImageLoader library for downloading images in an efficient way.
see this how to use universal Image loader for downloading images
One more solution for your requirement is Volley Library