I have a screen where I have to show two similar images on screen . The size of both these images is dynamic but they covers most of the screen. When I navigate to this screen in my app, I see a spike of 12MB in Memory Monitor in AndroidStudio meaning both these images is using that 12MB as there is no other UI element on that screen and as both these images are similar takes takes equal amount of screen space, I guess each consumes 6MB of memory when shown. The dimensions of both these images are 1174 x 1174 pixels and the size is 396KB in res directory.
I have tried using Glide but I see same memory spike when these images are loaded through Glide too. Even Glide can't help if the app tries to take more memory than available and there is heavy usage of images in other parts of my app. So there is always memory crunch and I'm getting lot of OutOfMemory exceptions in the app where these two images are shown.
So my question is how can I reduce the memory usage of those images? Also why does the image takes 6MB of memory when it's size is 396KB in res folder?
I am guessing you did not compress your images, use https://github.com/zetbaitsu/Compressor very great at image compression. Also i am also guessing you did use Glide caching strategies.
Glide, however, caches the original, full-resolution image and additionally smaller versions of that image. For example, if you request an image with 1000x1000 pixels, and your ImageView is 500x500 pixels, Glide will put both versions of the image in the cache.
DiskCacheStrategy.NONE caches nothing, as discussed
DiskCacheStrategy.SOURCE caches only the original full-resolution image. In our example above that would be the 1000x1000 pixel one
DiskCacheStrategy.RESULT caches only the final image, after reducing
the resolution (and possibly transformations) (default behavior)
DiskCacheStrategy.ALL caches all versions of the image
To answer your answer you need to manually keep track of the cache volume in android.Try forcing an garbage collection,Normally, VMs perform garbage collection only when absolutely needed, since it’s expensive. However, it can be useful to force garbage collection in certain circumstances. For example, when locating memory leaks, if you want to determine whether a large object was successfully released already, you can initiate garbage collection much more aggressively than usual.
Hope this was helpful.
Related
I have 5-6 PNG images each 2kb in size, and when i load them to my ImageView's, on Android Monitor it shows 12 MB more added to allocated memory.
i don't know what other factors are there that takes so much memory.
while i see other applications that are using many images per screen, they have no issue with performance and image quality.
I have tried using SVG's quality got better but performance dropped.
Is there a recommended way to display images without quality drop and memory friendly?
I'm building an application with very big sized images.
Almost all of my UI components are made of ImageViews.
I only have to show 12 images(ui components) on my first activity, but it consumes 80mb on startup.
The images are divided into each drawable directories using Android Drawable Importer.
By doing this I was able to reduce the runtime memory(which I can see on the Android studio's device monitor) to half, but it is still consuming 80~120mb of memories, which I believe is too much.
The first question is, isn't 80~120mb too much for a four screen(two activities, three fragments) application?
The second is, if it's too much then, what and how can I do to reduce memory usage?
When working with images keep in mind that there is a HUGE difference between compressed format (jpg, png..) and Bitmap. Computing the size of a Bitmap is pretty easy, it's width * height * 4 bytes (assuming that the bitmap has the default configuration argb888). So a full hd image that compressed is xy kb, when decompressed will occupy 8294400 bytes (~8mb). So my advice to reduce memory consumption is... scale down your images. You're asking if 80-120 mb is too much, well it seems like a lot but it really depends on what you're doing. What happen if you force garbage collection (there should be an icon in the device monitor)?Another thing to take into account is how to decompress the images, refer to this and use a library (Picasso, Glide..).
hi i am new to android and i have come across some memory management issues whilst using xml to position and design my activity layouts.
most images are around 100kb but vary in size e.g. image 1 will be 512x512, image 2 will be 120x320 etc.
at the moment the images are slowing down my app's performance and sometimes crashing.
Is there a way to reduce the amount of memory an image takes up on an app?
There's a number of steps that applications must go through in order to handle bitmaps sanely.
Small Compressed Size. It's important to balance quality vs. file size for your on-disk (or on-wire) formats. Being able to run PNG files through a lossy pre-processor, or choosing to use WEBP/JPG where needed are critical for each image in your app. Smaller PNG Files covers this more. The problem here, however, is that this doesn't help you with in memory size. Remember when your images are loaded from disk, they are decompressed into 32 bits-per-pixel in memory (in other words, no compression).
Compressed In Memory Format. Android provides the alternate 565 format, which uses only 16 bits per pixel, instead of the 32 bits for the 8888 format. If you're using an image that doesn't need alpha, you should consider the process discussed in Smaller Pixel Formats to leverage loading a bitmap as a 565.
Re-Using bitmap space. Most applicaitons that use thumbnails, only really have 10-20 of them visible on screen at one time (even though there may be thousands to load). The trick here is described in Re-using bitmaps. Basically, once a thumbnail is no longer needed, you can re-use it's space for an incoming thumbnail, rather than allocating a brand new one.
Display resolution. It makes no sense to load a 2MB image, to only display it as a thumbnail. Instead, you should be scaling the image to the resolution of what it'll display at, on the device. I discuss the most efficient way to load these images in the other SO post.
In general, Libraries like Picasso and Glide do a good job at providing APIs that make all this easier; but they are still going through these same processes under the hood.
You have 3 solutions you can do:
1st Solution:
Add in your AppManifest.xml in your application tag:
android:largeHeap="true"
This will try to prevent your app from causing OutOfMemoryError, but use it with caution.
Documentation: Whether your application's processes should be created with a large Dalvik heap. This applies to all processes created for the application. It only applies to the first application loaded into a process; if you're using a shared user ID to allow multiple applications to use a process, they all must use this option consistently or they will have unpredictable results.
Most apps should not need this and should instead focus on reducing their overall memory usage for improved performance. Enabling this also does not guarantee a fixed increase in available memory, because some devices are constrained by their total available memory.
2nd Solution:
If your images' file size are large, you can minimize them by using this online tool: http://compresspng.com/
3rd Solution:
You can use BitmapFactory for loading your images. Here is the Android Developers documentation: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
I am Working with one android tablet application in which lots of work with Images.
i have to load hundred of large bitmap images in scroll view. one image is around 1Mb to 3 Mb.
i have already scale images using bitmap factory and sample size, and also load all the images in Async task.
i am loading all the images from SD card.
Still facing OUT OF MEMORY issue after scrolling some images.
any help would be appreciated.
thanks in advance.
hi hope your solution.
you can user Univarsal Image Loader. This is better api for image download and store in catch. and get from catch. it's a great api for image operation.
this case is often come while we getting bitmap so just use lazy loading. just take a look on this example
http://sunil-android.blogspot.in/2013/09/lazy-loading-image-download-from.html
To prevent your application from soaking up CPU time without getting anything done, the JVM throws this Error so that you have a chance of diagnosing the problem.
Its because of large bitmap memory in stored in native area
so it better i suggest you use libraries like Universal Image Loader or
Bitmap Fun from android
You have to find out when the OOM error occurs. Is it when you have too much bitmap cache in memory without releasing or you just meet it when you're decoding certain bitmap?
For the first situation, I think you should manage your bitmap cache yourself or using some effective 3rd-party library which mentions above.
For the second situation, I've met it on some low-performance mobile(usually with 512MB or less memory), when you decode a bitmap to requested size, it may needs a rather large memory to store the bitmap, for 240dpi devices, it's about 800 * 480 * 4 = 1.5MB, however you may fail to allocate that much memory on some machines cause they may have strict memory manage strategy to prevent that much memory allocation. You should just catch the OOM error and continue rather than get a crush.
Loading a bitmap in 1280x800 display will take 1280x800x4 byte (~4MB) memory. Java heap size is limited (~50MB) so you can not use lots of large bitmaps in your app. Using cache and reusing bitmap objects are necessary while working with bitmaps but another useful trick is to use larger hip size! to do so, add android:largeHeap="true" to Application tag in your manifest. It increases hip size to 4 or 5 times larger (~250MB) than normal. I hope this help other people reaching this thread while they search!
In my app, I put PNG images into drawable directory and use them as activity backgrounds. Since the background image usually cover the whole screen, they are big and use a lot of memory.
My background images are total opaque. Is there any way that I can optimize those background images, so they can take less memory? I heard that we can reduce the color-depth of the images so they take less memory when loaded, but I don't know how to reduce the color-depth? What tool can I use?
Thanks.
You can try converting your drawable to a bitmap
and then using BitmapFactory.Options to reduce the sample size, etc.
I find the use of Universal Image Loader Library to be one of the best in providing various configurations for Image handling. And in those Configurations, we find the option to load the image in RGB_565 encoding which is capable of reducing memory consumption by upto 50% (have seen the results practically) and that is capable of making a huge impact on the memory consumption of your app.
Use .bitmapConfig(Bitmap.Config.RGB_565) in display options. Bitmaps in RGB_565 consume 2 times less memory than in ARGB_8888.