Android performance optimization: asynchronous image loading tool with dual cache (LruCache + SoftReference ),

Source: Internet
Author: User

Android performance optimization: asynchronous image loading tool with dual cache (LruCache + SoftReference ),

Previously, I used the LruCache algorithm to implement image caching in Guo Dashen's blog. here, I followed his ideas and wrote one myself. concurrentHashMap <String, SoftReference <Bitmap> is added to implement level-2 cache, because ConcurrentHashMap is thread-safe with multiple locks and supports high concurrency. this operation is suitable for frequent accesses to read memory.


The following idea is that the LruCache class provided by the system is used as a level-1 cache, with a size of 1/8 of the running memory. When the LruCache capacity is full, images removed by the system are automatically placed in the second-level cache. To avoid OOM problems, SoftReference soft reference is added here, when the system is about to OOM, it will automatically clear the image memory. Of course, when the memory is sufficient, it will continue to save the second-level cached images. it should be emphasized that SoftReference should not be used as a level-1 cache. Currently, garbage collection in java enhances the soft reference collection mechanism for SoftReference. It is only suitable for temporarily saving some data caches, it is not suitable for long term (not a real long term ).


Use the Code directly:

/*** Created on 3/11/2015 * <br> image asynchronous loading tool (supports local image loading, network image URL loading, and project image resource loading) * <br> supports dual-Cache: lruCache and SoftReference * @ author Mr. et **/public class ImageLoadManager {/** image source type: file, network, resource ID **/public enum IMAGE_LOAD_TYPE {FILE_PATH, FILE_URL, FILE_RESOURCE_ID} private String TAG = "ImageLoadManager... "; private Context context; private Set <ImageLoadTask> taskCollection;/** maximum memory **/final static int maxCacheSize = (I Nt) (Runtime. getRuntime (). maxMemory ()/8);/** establishes thread security and supports highly concurrent containers **/private static ConcurrentHashMap <String, SoftReference <Bitmap> currentHashmap = new ConcurrentHashMap <String, softReference <Bitmap> (); public ImageLoadManager (Context context) {super (); this. context = context; taskCollection = new HashSet <ImageLoadManager. imageLoadTask> ();} private static LruCache <String, Bitmap> BitmapMemoryCache = new LruCache <String, Bitmap> (maxCacheSize) {@ Overrideprotected int sizeOf (String key, Bitmap value) {if (value! = Null) {return value. getByteCount (); // return value. getRowBytes () * value. getHeight (); // method of the old version} else {return 0 ;}/// this method is called when the memory of LruCache is full, remove the oldValue element to free up space for adding @ Overrideprotected void entryRemoved (boolean evicted, String key, Bitmap oldValue, Bitmap newValue) {if (oldValue! = Null) {// when the hard reference cache capacity is full, the LRU algorithm is used to transfer recently unused images to the soft reference cache currentHashmap. put (key, new SoftReference <Bitmap> (oldValue ));}}}; /*** Method for displaying images by providing image resource IDs * @ param loadType image loading type * @ param imageResourceID image resource ID * @ param imageView display image ImageView */public void setImageView (IMAGE_LOAD_TYPE loadType, int imageResourceID, ImageView imageView) {if (loadType = IMAGE_LOAD_TYPE.FILE_RESOURCE_ID) {// if (ifResourceIdExist (imageR EsourceID) // {// imageView. setImageResource (imageResourceID); //} else {// ing cannot get the image, the default image is displayed. // imageView. setImageResource (R. drawable. pic_default); //} try {imageView. setImageResource (imageResourceID); return;} catch (Exception e) {Log. e (TAG, "Can find the imageID of" + imageResourceID); e. printStackTrace ();} // default image imageView. setImageResource (R. drawable. pic_default) ;}}/*** how to display an image by providing the image file link or download link * @ param lo AdType image loading type * @ param imageFilePath: local file address of the image file or download link of the network URL * @ param imageView: ImageView of the image */public void setImageView (IMAGE_LOAD_TYPE loadType, String imageFilePath, imageView imageView) {if (imageFilePath = null | imageFilePath. trim (). equals ("") {imageView. setImageResource (R. drawable. pic_default);} else {Bitmap bitmap = getBitmapFromMemoryCache (imageFilePath); if (bitmap! = Null) {imageView. setImageBitmap (bitmap);} else {imageView. setImageResource (R. drawable. pic_default); ImageLoadTask task = new ImageLoadTask (loadType, imageview1_taskcollection.add(task1_task.exe cute (imageFilePath) ;}}/ *** get an image from LruCache, if it does not exist, null * @ param key is returned. The key value can be the filePath of the image file, which can be the image URL address * @ return Bitmap object, or null */public Bitmap getBitmapFromMemoryCache (String key) {try {if (BitmapMemoryCache. get (Key) = null) {if (currentHashmap. get (key )! = Null) {return currentHashmap. get (key ). get () ;}return BitmapMemoryCache. get (key);} catch (Exception e) {e. printStackTrace ();} return BitmapMemoryCache. get (key);}/*** put the image into the cache * @ param key * @ param bitmap */private void addBitmapToCache (String key, Bitmap bitmap) {BitmapMemoryCache. put (key, bitmap);}/*** asynchronous image loading * @ author Mr. et **/private class ImageLoadTask extends AsyncTask <String, Void, Bitmap> {pr Ivate String imagePath; private ImageView imageView; private IMAGE_LOAD_TYPE loadType; public ImageLoadTask (IMAGE_LOAD_TYPE loadType, ImageView imageView) {this. loadType = loadType; this. imageView = imageView;} @ Overrideprotected Bitmap doInBackground (String... params) {imagePath = params [0]; try {if (loadType = IMAGE_LOAD_TYPE.FILE_PATH) {if (new File (imagePath ). exists () {// read the image BitmapFactory from the local FILE. options Opts = new BitmapFactory. options (); opts. inSampleSize = 2; Bitmap bitmap = BitmapFactory. decodeFile (imagePath, opts); // put the acquired image into the cache addBitmapToCache (imagePath, bitmap); return bitmap;} return null;} else if (loadType = IMAGE_LOAD_TYPE.FILE_URL) {// download the image byte [] datas = getBytesOfBitMap (imagePath); if (datas! = Null) {// BitmapFactory. options opts = new BitmapFactory. options (); // opts. inSampleSize = 2; // Bitmap bitmap = BitmapFactory. decodeByteArray (datas, 0, datas. length, opts); Bitmap bitmap = BitmapFactory. decodeByteArray (datas, 0, datas. length); addBitmapToCache (imagePath, bitmap); return bitmap;} return null ;}} catch (Exception e) {e. printStackTrace (); FileUtils. saveExceptionLog (e); // other operations can be customized} return null ;}@ Overrideprotected void onPostExecute (Bitmap bitmap) {try {if (imageView! = Null) {if (bitmap! = Null) {imageView. setImageBitmap (bitmap);} else {Log. e (TAG, "The bitmap result is null... ") ;}} else {Log. e (TAG, "The imageView is null... "); // The default image imageView is displayed when the image fails to be obtained. setImageResource (R. drawable. pic_default) ;}} catch (Exception e) {e. printStackTrace (); FileUtils. saveExceptionLog (e) ;}}/ *** convert InputStream to byte [] * @ param inStream * @ return * @ throws Exception */private byte [] readStream (InputStream inStream) Throws Exception {ByteArrayOutputStream outStream = new ByteArrayOutputStream (); byte [] buffer = new byte [2048]; int len = 0; while (len = inStream. read (buffer ))! =-1) {outStream. write (buffer, 0, len);} outStream. close (); inStream. close (); return outStream. toByteArray ();}/*** get the downloaded image and convert it to byte [] * @ param urlStr * @ return */private byte [] getBytesOfBitMap (String imgUrl) {try {URL url = new URL (imgUrl); HttpURLConnection conn = (HttpURLConnection) url. openConnection (); conn. setConnectTimeout (10*1000); // 10sconn. setReadTimeout (20*1000); conn. setRequestMethod (" GET "); conn. connect (); InputStream in = conn. getInputStream (); return readStream (in);} catch (IOException e) {e. printStackTrace ();} catch (Exception e) {e. printStackTrace ();} return null;}/*** whether the resource ID is valid * @ param resourceId resource ID * @ return */private boolean ifResourceIdExist (int resourceId) {try {Field field = R. drawable. class. getField (String. valueOf (resourceId); Integer. parseInt (field. get (null ). toSt Ring (); return true;} catch (Exception e) {e. printStackTrace ();} return false;}/*** cancel all tasks */public void cancelAllTask () {if (taskCollection! = Null) {for (ImageLoadTask task: taskCollection) {task. cancel (false );}}}}

In addition, if you need a better experience, you can also add a third-level caching mechanism, such as caching images to local disk storage space. but I don't want these images cached locally to be scanned by other applications or viewed by users. What should I do? There are several ideas here, such as converting images into string storage using encryption algorithms, or converting images into custom-format unknown files in hidden places (this method is adopted by many applications ). try to implement it by yourself ~




Related Article

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.