Android Picture Cache Imagecache

Source: Internet
Author: User

Why do you cache?

It's easy to load a picture in the UI interface, but if you need to load more than one large image, things can get more complicated. In many cases (such as widgets such as a ListView, GridView, or Viewpager), the total number of pictures on the screen increases with the scrolling of the screen and is essentially infinite.

To keep memory usage in a stable range, prevent oom from appearing, these components recycle the child view after it draws the screen, and re-display the new picture, and the garbage collection mechanism frees up the memory space of the picture that is no longer displayed.       However, the loading and retrieval of images is not conducive to the smooth operation of the image, and the memory or disk cache will help solve this problem, so that the loaded images can be loaded quickly. On the cache, there are two main levels of Cache:lrucache and Disklrucache. The former is memory-based and the latter is disk-based.

How do I cache in memory?

The memory cache allows you to quickly load cached pictures, but consumes the memory space of your app. The LRUCache class (which can be supported to sdk4 through a Compatibility Pack) is ideal for image caching, which stores images by Linkedhashmap keeping images strong, and frees up early caches when the cache space exceeds the set limit.

Note: In the past, common memory cache implementations were passed SoftReference or weakreference, but this is not recommended. The Android2.3 (API Level 9) garbage collector began to collect soft/weak references more aggressively, which made them quite ineffective. Also, before Android 3.0 (API level 11), the visible bitmap stored in native memory will not be released, which may cause the application to temporarily exceed its memory limit and crash.

In order to set the appropriate size for LRUCache, the following factors need to be considered:

    • How big is the free memory in your app?

    • How many pictures do you want to display in the screen at once? How many pictures do you want to display?

    • What is the screen size and density of the device? The ultra-high screen density device (XHDPI) requires a larger cache space like the Galaxy Nexus than the Nexus S (HDPI) when caching the same picture.

    • What is the size and properties of the picture and how much memory space is required?

    • How often are images accessed? Is it more frequent than other pictures? If this is the case, you may want to consider storing the image in memory for a long time or using a different caching strategy for different types of images.

    • How to balance quality with quantity, something you might store some commonly used low-quality pictures for users to display, and then loads to load high-quality pictures via an async line.

Picture caching scheme does not have a fixed pattern using all of the applications, you need to base on the application of specific scenarios for analysis, choose the right solution to do, the cache is too small to play the advantage of caching, too large may occupy too much memory, reduce application performance, or a memory overflow exception occurred,

Here is an example of using LRUCache:

Private LruCache Mmemorycache;                                                                          
{     ...     Get Memory class of this device, exceeding this amount would throw an OutOfMemory exception.     Final int memclass = ((Activitymanager) Context.getsystemservice (Context.activity_service)). Getmemoryclass ();                                                                              Use 1/8th of the available memory for this memory cache.     Final int cacheSize = 1024x768 * 1024x768 * MEMCLASS/8;                                                                              
    {         @Override        
        {             //The cache size is measured in bytes rather than number of items.             return Bitmap.getbytecount ();         }     };     ... }                                                                          
{     
    {         mmemorycache.put (key, bitmap);     } }                                                                          
{     return Mmemorycache.get (key);}

Note: In this example, one-eighth of the memory is allocated to the image cache, which is approximately 4MB (32/8) in the normal/hdpi device. Girdview requires 1.5M picture space (800*480*4 bytes) in a 800x480 resolution device in full screen, so you can cache 2.5-screen images in memory.

Use LRUCache to add a picture to ImageView first check whether the picture exists, if the direct line ImageView, otherwise through the background line loads download Picture:

{     final String ImageKey = string.valueof (resId);                                                              Final Bitmap Bitmap = Getbitmapfrommemcache (ImageKey);     
    {         imageview.setimagebitmap (bitmap);     
    
    {         Imageview.setimageresource (r.drawable.image_placeholder);         Bitmapworkertask task = new Bitmapworkertask (imageView);         Task.execute (resId);     } }

Bitmapworkertask needs to add the loaded picture to the cache:

{     ...     Decode image in background.     @Override    
    {         final Bitmap Bitmap = Decodesampledbitmapfromresource (Getresources (), Params[0], (+));         Addbitmaptomemorycache (String.valueof (Params[0]), bitmap);         return bitmap;     }     ... }

How do I use disk caching?

The memory cache is efficient for accessing recently used pictures, but you cannot guarantee that it will always be in the cache. Large data volumes like Girdview are easily filled with memory caches. Your app may be interrupted by "incoming calls", may be killed in the background, the memory cache will expire, and once the user is back in the app, you need to re-process each picture.

In this case we can use the disk cache to store processed pictures, when the picture is no longer in memory, reduce the reload time, of course, loading pictures from disk than in memory slower, need to do in the background thread, because the disk read time is unknown.

Note: If you frequently visit pictures, ContentProvider should be a good place to store pictures, such as: Gallery image management app.

The following is a simple disklrucache implementation. However, the recommended implementation of the Disklrucache scheme, please refer to the Android4.0 (Libcore/luni/src/main/java/libcore/io/disklrucache.java) source code. This article uses a simple implementation from a previous version (another implementation in Quick search).

The display is an example of a simple implementation of the Disklrucache update:

Private Disklrucache Mdiskcache; private static final int disk_cache_size = 1024 * 1024 * 10; 10MB private static final String Disk_cache_subdir = "thumbnails";                                    
{     ...     Initialize Memory Cache     ...     File Cachedir = Getcachedir (this, disk_cache_subdir);     Mdiskcache = Disklrucache.opencache (this, Cachedir, disk_cache_size);     ... }                                    
{     ...     Decode image in background.     @Override    
    {         final String ImageKey = string.valueof (Params[0]);                                            Check disk cache in background thread         Bitmap Bitmap = Getbitmapfromdiskcache (ImageKey);                                            
        
            Not found in disk cache             //Process as normal             final Bitmap Bitmap = Decodesampledbitmapfromresource (getresources (), Params[0], (+));         }                                            ADD final bitmap to caches         Addbitmaptocache (string.valueof (ImageKey, bitmap);                                            return bitmap;     }     ... }                                    
{     //ADD to memory cache as before     
    {         mmemorycache.put (key, bitmap);     }                                        Also Add to disk cache     
    {         mdiskcache.put (key, bitmap);     } }                                    
{     return Mdiskcache.get (key);}                                    
{     //Check If media is mounted or storage are built-in, if so, try and use external cache dir otherwise use internal CA Che dir     
                             ! Environment.isexternalstorageremovable ())?                              
                             Context.getcachedir (). GetPath ();                                        return new File (CachePath + file.separator + uniqueName); }

The memory cache check is done in the UI thread, and the disk cache is checked in the background thread. The hard disk operation should not be in the UI thread. After the picture is processed, it should be added to the memory and disk cache in use.

How are configuration changes handled?

When the application is running in a configuration change, such as when the screen orientation changes in order to apply the new configuration Android will destroy the rerun of the current activity, at this time, in order to give users a fast, gentle user experience you may not want to reload the picture.

Thanks to the caching technique you ran, the cache can be passed to the new activity via Setretaininstance (true), and after the activity restarts, you can reuse the existing cache with the attached fragment. This will allow you to quickly load into the ImageView.

Here is an example of reusing an existing cache with fragment when the configuration changes:

Private LruCache Mmemorycache;                   
{     ...     Retainfragment mretainfragment =             retainfragment.findorcreateretainfragment (Getfragmentmanager ());     Mmemorycache = Retainfragment.mretainedcache;     
    {         
        {             ...///Initialize cache here as usual         }         mretainfragment.mretainedcache = Mmemorycache;     }     ... }                   
{     private static final String TAG = "Retainfragment";     Public LruCache Mretainedcache;                       Public retainfragment () {}                       
    {         Retainfragment fragment = (retainfragment) fm.findfragmentbytag (TAG);         
        {             fragment = new Retainfragment ();         }         return fragment;     }                       @Override    
    {         super.oncreate (savedinstancestate);         Setretaininstance (True);     } }

To test, force the screen to rotate when using and not using fragment, and you will find that there is little lag when loading pictures from the reserved memory cache.

Transfer from: Link

Android Picture Cache Imagecache (RPM)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.