As we all know, the VM Heap Size for Android Apps is limited.
(mostly to 16,24,32,48 or 64 MB of RAM depending on the hardware)
we can get the actual Heap Size with
ActivityManager am = (ActivityManager)this.getSystemService(ACTIVITY_SERVICE);
Toast.makeText(this, "HEAP SIZE: " + am.getMemoryClass() + "MB", 1).show();
.
But, what is the memory strategy if I open a new Intent???:
Intent intent = new Intent(MainActivity.this, NewActivity.class);
MainActivity.this.startActivity(intent);
Does this new activity get the full heap size and the old activity is holding in the background, and its memory is cached?
Or does the intent get a complete new VM?
I have a very memory intense App with heavily filles Grid- and ListViews.
Since Android 3.0, Bitmaps are allocated inside the Heap, and that causes a lot of headache and trouble with OutOfMemory Errors... I was wondering if I can outsorce the memory hungry Views in their own Intents. <-- does this make any sense?
Every process has one heap, of whatever size the device specifies (minimum 16 MB if Google Play is installed on the device).
All of your app's components must run within this heap, as your app is a single process. So all your Activities, Services, BroadcastReceivers share the same heap.
When you launch a new Activity, your previous Activity is pushed into the background. Due to this, its onPause() is called, and you should use that method to free up memory (remove loaded bitmaps etc) if you need to.
Also, outsorce the memory hungry Views in their own Intents makes no sense because Intents are used to start Application components like Activities and Services. You cannot use a View with an Intent. Instead, you should be scaling your bitmaps and loading only the required size, and make use of technique like lazy loading to make sure you don't have more bitmaps in memory than required.
I agree with Raghav Sood. I have added a bit more of how to display images in listview or gridview.
I have used Universal Image loader to display large number of images in listview.
You should recycle bitmaps when not in use.
http://www.youtube.com/watch?v=_CruQY55HOk. Talk is about memoy management and memory leaks and how to avoid it. If you ever run into memory leaks you can use a MAT Analyzer to find memory leaks. The video also talks about using MAT Analyzer and demonstrates how to get rid of memory leaks.
When you display images in listview you need to recycle the views. Views that are visible are not recycled.
To display images in gridview or listview you can use univarsal image loader. A improved version of lazy loading. Images are cached. You can display images localy or from a server.
https://github.com/nostra13/Android-Universal-Image-Loader
File cacheDir = StorageUtils.getOwnCacheDirectory(context, "your folder");
// Get singletone instance of ImageLoader
imageLoader = ImageLoader.getInstance();
// Create configuration for ImageLoader (all options are optional)
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(a)
// You can pass your own memory cache implementation
.discCache(new UnlimitedDiscCache(cacheDir)) // You can pass your own disc cache implementation
.discCacheFileNameGenerator(new HashCodeFileNameGenerator())
.enableLogging()
.build();
// Initialize ImageLoader with created configuration. Do it once.
imageLoader.init(config);
options = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.stub_id)//display stub image
.cacheInMemory()
.cacheOnDisc()
.displayer(new RoundedBitmapDisplayer(20))
.build();
In your getView()
ImageView image=(ImageView)vi.findViewById(R.id.imageview);
imageLoader.displayImage(imageurl, image,options);//provide imageurl, imageview and options
You can configure with other options to suit your needs.
Along with Universal Image Loader you can view holder for smooth scrolling and performance. http://developer.android.com/training/improving-layouts/smooth-scrolling.html.
http://www.youtube.com/watch?v=wDBM6wVEO70. The talk is about viewholder and performance.
Related
I'm loading about 50 images. In my activity I have this configuration
DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
.cacheOnDisk(true).cacheInMemory(true)
.imageScaleType(ImageScaleType.EXACTLY)
.resetViewBeforeLoading(true)
.displayer(new FadeInBitmapDisplayer(300))
.build();
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
.defaultDisplayImageOptions(defaultOptions)
.memoryCache(new WeakMemoryCache())
.diskCacheSize(100 * 1024 * 1024)
.build();
ImageLoader.getInstance().init(config);
in binderdata
ImageLoader imageLoader = ImageLoader.getInstance();
imageLoader.displayImage(uri, holder.iv_img);
Some images are loaded, but some are not and I get OutOfMemory error.
Check this tips from Useful Info
If you often got OutOfMemoryError in your app using Universal Image
Loader then:
Disable caching in memory. If OOM is still occurs then it seems your app has a memory leak. Use MemoryAnalyzer to detect it. Otherwise
try the following steps (all of them or several):
Reduce thread pool size in configuration (.threadPoolSize(...)). 1 - 5 is recommended.
Use .bitmapConfig(Bitmap.Config.RGB_565) in display options. Bitmaps in RGB_565 consume 2 times less memory than in ARGB_8888.
Use .imageScaleType(ImageScaleType.EXACTLY) (Your already use this tips)
Use .diskCacheExtraOptions(480, 320, null) in configuration
Hope this helps!!
1.I would suggest you to checkout Image Management Library by Facebook that is Fresco that is pretty awesome and mature as compared to other Image Loading Library.
2.Fresco handles all the things caching of images with 3 Tier architecture ( BITMAP_MEMORY_CACHE, ENCODED_MEMORY_CACHE and DISK_CACHE). It also reduces OOM(Out Of Memory) issues. When image in a view goes out of screen it automatically recycles the bitmap, hence releasing the memory.
3.Fresco has SimpleDraweeView as custom image view which supports Rounded Corners and Circles link and supports Animated(.gif, .webp) as well as Normal Images(.jpg, .png).
I have a problem using the Universal Image Loader Library.
Unfortunately, the Library causes huge memory usage of my application.
I have a ScrollView (there are tons of reasons why I am using a ScrollView instead of a ListView, most of them have to do with custom insertion and item selection animations) holding about 20 custom Views.
Each of those custom views consists of some TextViews as well as an ImageView.
And now here is the thing:
The Images dispalyed in the ImageViews are downloaded from the Internet and all have around 100-150kb (dimension 640 x 320) each. If I download the Images using the UniversalImageLoader my app crashes with an OutOfMemoryException because it uses around 80Mb of memory.
If I do not download the Images, and just put in a Hard-Coded Image with the size of 1200kb (dimension 1920 x 1080) per custom view, my app only consumes around 40Mb of memory.
What am I doing wrong using the UniversalImageLoader when downloading ten times smaller Images causes my app to use up twice as much memory?
I disabled all caching mechanisms but the problem still persists.
Here is my UniversalImageLoader setup:
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(c)
.build();
ImageLoader.getInstance().init(config);
DisplayImageOptions options = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.loading)
.showImageForEmptyUri(R.drawable.loading)
.showImageOnFail(R.drawable.loading)
.cacheInMemory(false)
.cacheOnDisc(false)
.imageScaleType(ImageScaleType.IN_SAMPLE_INT) // default
.build();
And in code, I call it like this:
ImageLoader im = ImageLoader.getInstance();
im.displayImage("myurl", myimageview, options);
What am I doing wrong? Why is the UniversalImageLoader using up so much memory?
For all the other people out there having the same issues:
I managed to minimize my Memory usage and get rid of the OutOfMemoryException by following these guidelines:
https://github.com/nostra13/Android-Universal-Image-Loader#useful-info
The most important part for me was to reduce the ThreadPoolSize down to 2. I could not feel any performance changes after setting it down.
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(c)
.threadPoolSize(2)
.build();
DisplayImageOptions options = new DisplayImageOptions.Builder()
// other options
.bitmapConfig(Bitmap.Config.RGB_565)
.imageScaleType(ImageScaleType.EXACTLY)
// other options
.build();
This reduced my applications total memory consumption by about 35%.
I can't find in any really credible source explaining what LazyList is. Anyone?
Lazy List is lazy loading of images from sd-card or from server using urls. It is like on demand loading of images.
Images can be cached to a local sd-card or your phone's memory. URL is considered the key. If the key is present in the sd-card, images get displayed from sd-card, otherwise it downloads the image from the server and caches it to a location of your choice. You can set a cache limit. You can also choose your own location to cache images. Cache can also be cleared.
Instead of the user waiting to download large images and then displaying them, lazy list loads images on demand. Since images are cached, you can display images offline.
https://github.com/thest1/LazyList. Lazy List
In your getview
imageLoader.DisplayImage(imageurl, imageview);
ImageLoader Display method
public void DisplayImage(String url, ImageView imageView) //url and imageview as parameters
{
imageViews.put(imageView, url);
Bitmap bitmap=memoryCache.get(url); //get image from cache using url as key
if(bitmap!=null) //if image exists
imageView.setImageBitmap(bitmap); //display iamge
else //downlaod image and dispaly. add to cache.
{
queuePhoto(url, imageView);
imageView.setImageResource(stub_id);
}
}
An alternative to Lazy List is Universal Image Loader
https://github.com/nostra13/Android-Universal-Image-Loader. It is based on Lazy List (it works on the same principle), but it has lot of other configurations. I would prefer to use Universal Image Loader because it gives you more configuration options. It can display an error image if a download failed. It can display images with rounded corners. It can cache on disc or memory. It can compress an image.
In your custom adapter constructor
File cacheDir = StorageUtils.getOwnCacheDirectory(a, "your folder");
// Get singletone instance of ImageLoader
imageLoader = ImageLoader.getInstance();
// Create configuration for ImageLoader (all options are optional)
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(a)
// You can pass your own memory cache implementation
.discCache(new UnlimitedDiscCache(cacheDir)) // You can pass your own disc cache implementation
.discCacheFileNameGenerator(new HashCodeFileNameGenerator())
.enableLogging()
.build();
// Initialize ImageLoader with created configuration. Do it once.
imageLoader.init(config);
options = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.stub_id)//display stub image
.cacheInMemory()
.cacheOnDisc()
.displayer(new RoundedBitmapDisplayer(20))
.build();
In your getView()
ImageView image=(ImageView)vi.findViewById(R.id.imageview);
imageLoader.displayImage(imageurl, image,options);//provide imageurl, imageview and options
You can configure Universal Image Loader with other options to suit your needs.
Along with LazyList/Universal Image Loader you can view this website for smooth scrolling and performance.
http://developer.android.com/training/improving-layouts/smooth-scrolling.html.
AFAIK, I'll explain you with the example
If you list contain lot of images with Text, it will take some time for your list to load because you need to download images and you need to populate them in the list. Suppose if your list contains 100 images It will take lot of time to download each image and to show it the listitem. To make the user wait until the images loads is not user friendly.
so What we need to do. At this point of time lazy list comes into picture. It is the idea that let the images be loaded in background and show text mean while.
Everybody know that listview recycle its views for every view. i.e if your listview contains 40 elemtns then listview won't allocate memory for 40 items instead it allocate memory for the visible items, i.e say you can see only 10 items at a time. so listview will allocate 10 items meemory.
So When ever you scroll the view, then the view will refresh. because of the you'll lose your reference to images and you need to download them agian. in order to avoid that, caching comes into picture.
This example is based on my knowledge in listview, I am not saying this is only correct. There might be wrong in the answer, if any body find feel free to inform me.
I think this is the other way around. AFAIK, Lazy Loading is the definition, where you actually load the data only when you need it, and it's a good design practice.
So I believe the same applies for this, only this time it's being referring to the List View.
If I'm wrong, please correct me.
The best example of lazy list is facebook notifications,messages,requests. when you scroll then data will be load.
I'm working on a music player app for android and am trying to find the best way of dealing with images. I'm loading artist images from the web, and album images either from the MediaStore or the web depending on the circumstances. I will need to add either set of images (artist or album) to listViews at different times.
Storing the images in memory (HashTable) would make loading very quick, but could become impractical if the user has a very large music library.
However I can't load them on an "as needed" basis because I need to bind them to a listView. In addition, I have a notification that displays the artist image and provides navigation controls. If I wait to load the image when the user clicks the next button, it might not load before the notification view updates.
Is the best approach to connect to the Net on first load and then save the files locally, and then load them as needed? If I do it this way, will the image be loaded quickly enough to keep up with a user fast-clicking the next button and refreshing the artist image view?
Thanks,
Use a listview or gridview to display images.
You can use https://github.com/nostra13/Android-Universal-Image-Loader Universal Image Loader to load images either form MediaStore or from the web. Uses caching. Based on Lazy Loading but has more configuration options.
In you adapter contructor
File cacheDir = StorageUtils.getOwnCacheDirectory(a, "UniversalImageLoader/Cache");
// Get singletone instance of ImageLoader
imageLoader = ImageLoader.getInstance();
// Create configuration for ImageLoader (all options are optional)
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(a)
// You can pass your own memory cache implementation
.discCache(new UnlimitedDiscCache(cacheDir)) // You can pass your own disc cache implementation
.discCacheFileNameGenerator(new HashCodeFileNameGenerator())
.enableLogging()
.build();
// Initialize ImageLoader with created configuration. Do it once.
imageLoader.init(config);
options = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.stub_id)//dummy image
.cacheInMemory()
.cacheOnDisc()
.displayer(new RoundedBitmapDisplayer(20))
.build();
In your getView()
ImageView image=(ImageView)vi.findViewById(R.id.imageview);
imageLoader.displayImage(imageurl, image,options);
You can also use https://github.com/thest1/LazyList. Also uses caching.
Also use a ViewHolder in listview or grdiview. http://developer.android.com/training/improving-layouts/smooth-scrolling.html.
Load your images from local file storage or MediaStore in the getView() function of your ListView's ListAdapter or SimpleListAdapter. The adapter will take care of only calling getView() when necessary for the item(s) needed by position. Your system will be fast enough to load the images in this manner when they are needed.
You will have to fetch all images from the web at an earlier time and store them in the local filesystem so they are available for display by the ListView.
I am trying to use a disk cache (not a memory cache) so i download my images from an urls and put it in a grid view. I want to download my images only one time.
I found this example (bitmapFun) in google site: http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html
I found this example a bit complicated.
There are many objects in util package (AsyncTask, DiskLruCache, ImageCache, ImageFetcher, ImageResizer, ImageWorker, Utils)
Is there a way or a tutorial that show how can i use a disk Lru cache without using all those object.
I don't want to resize my image and i was not able to remove ImageResizer class.
Here you have good answer :Android image caching. Quotation :
"Consider using Universal Image Loader library by Sergey Tarasevich. It comes with:
//Multithread image loading. It lets you can define the thread pool size
//Image caching in memory, on device's file sytem and SD card.
//Possibility to listen to loading progress and loading events
Universal Image Loader allows detailed cache management for downloaded images, with the following cache configurations:
UsingFreqLimitedMemoryCache: //The least frequently used bitmap is deleted when the cache size limit is exceeded.
LRULimitedMemoryCache: //The least recently used bitmap is deleted when the cache size limit is exceeded.
FIFOLimitedMemoryCache: //The FIFO rule is used for deletion when the cache size limit is exceeded.
LargestLimitedMemoryCache: //The largest bitmap is deleted when the cache size limit is exceeded.
LimitedAgeMemoryCache: //The Cached object is deleted when its age exceeds defined value.
WeakMemoryCache: //A memory cache with only weak references to bitmaps.
A simple usage example:
ImageView imageView = groupView.findViewById(R.id.imageView);
String imageUrl = "http://domain.com/image.png";
ImageLoader imageLoader = ImageLoader.getInstance();
imageLoader.init(ImageLoaderConfiguration.createDefault(context));
imageLoader.displayImage(imageUrl, imageView);
This example uses the default UsingFreqLimitedMemoryCache.