First, the problem description |
Use LRUCache, asynctask to achieve batch image loading and meet the following technical requirements
1, read the picture from the cache, if not in the cache, open the asynchronous thread (asynctask) load the picture, and put into the cache
2. Remove invalid asynchronous threads in time; Ensure that images are loaded asynchronously without ordering
3, only the current screen visible part of the cache, loading pictures asynchronously
4. Optimize performance to eliminate oom
Second, Case introduction |
Case implementation Photo Wall effect
Third, the main technology |
LruCache
Memory Caching technology , a component that is specifically used in Android for Image cache processing, using the main steps
(1) Set the memory size of the cached image, as set to 1/8 of the memory of the phone (when the cached image reaches the pre-set value, then the least recently used image will be recycled) code as follows:
Gets the maximum available memory of the application int maxmemory = (int) runtime.getruntime (). MaxMemory (); int cacheSize = maxmemory/8;//Set the picture cache size to the maximum available memory for the program 1/8mmemorycache = new lrucache<string, bitmap> (cacheSize) { @Override protected int sizeOf (String key, Bitmap Bitmap) { return bitmap.getbytecount (); } };
(2) Put the picture in the cache (the key-value pairs in the LRUCache are usually URLs and corresponding images, respectively)
Mmemorycache.put (key, bitmap);
(3) Take a picture from the cache
Mmemorycache.get (key);
Asynctask
For time-consuming operations such as loading a picture requires that you do not block the UI thread, you must use an asynchronous task. Asynctask is a simple and lightweight component that does not require the use of Thread+handler to implement asynchronous tasks. The steps to implement Asynctask are as follows:
(1) Extension sub-asynctask, such as
Class Bitmapworkertask extends Asynctask<string, Void, bitmap>
(2) Several methods of rewriting Asynctask
OnPreExecute (), the method will be called by the UI thread before performing the actual background operation. You can do some preparatory work in this method, such as displaying a progress bar on the interface.
Doinbackground (Params ...), executed after the OnPreExecute method executes, runs in a background thread and is primarily responsible for performing those very time-consuming background computations, such as loading pictures
OnPostExecute (Result), which will be called by the UI thread after Doinbackground execution completes, will be passed to the UI thread by the method in the background
(3) Execute (Params ...) in the UI thread by calling Asynctask;
Start the asynchronous task and pass in the data to the background task, execution order OnPreExecute ()---Doinbackground (Params ...) --OnPostExecute (Result)
Experience: loading a large number of images requires that each picture be run in a background task, so you need to use the collection to record all the tasks that are being downloaded or waiting to be downloaded
set<bitmapworkertask> taskcollection=new hashset< bitmapworkertask > ();
When there are no pictures in the cache, add tasks and start asynchronous processing, fragment code such as:
if (bitmap = = null) {//If the cache does not have bitmapworkertask task = new Bitmapworkertask (); Taskcollection.add (Task); Task.execute (IMAGEURL);//Perform an asynchronous task and pass in the loaded picture URL address}
Be careful to remove completed tasks in a timely manner, such as the following code
protected void OnPostExecute (Bitmap Bitmap) {.... taskcollection.remove (this);}
and cancel the task that is being performed while the adapter control is sliding, the fragment code is as follows:
public void onscrollstatechanged (Abslistview view, int scrollstate) {//Only when the GridView is stationary to download the picture, the GridView slide cancels all the tasks that are being downloaded if ( Scrollstate = = Scroll_state_idle) {loadbitmaps (Mfirstvisibleitem, mvisibleitemcount);} else {cancelalltasks ();// Cancels all tasks that are downloading or waiting to be downloaded. }}public void Cancelalltasks () {if (taskcollection! = null) {for (Bitmapworkertask task:taskcollection) {task.cancel (FAL SE);}}}
1, mainactivity
public class Mainactivity extends Activity {private GridView mphotowall; Private Photowalladapter adapter;private arraylist<file> list; protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview (R.layout.activity_main); List = new arraylist<file> (); Getallfiles (New File ("/sdcard")); Mphotowall = (GridView) Findviewbyid (R.id.photo_wall); adapter = new Photowalladapter (this, 0, list, mphotowall); Mphotowall.setadapter (adapter); }/** * Gets the specified directory slice file */private void Getallfiles (file root) {file files[] = Root.listfiles (); if (Files! = null) for (File f:files) {if (F.isdirectory ()) {Getallfiles ( f); } else {if (F.getname (). IndexOf (". png") > 0 | | f.getname (). IndexOf (". jpg ") > 0 | | F.getname (). IndexOf (". jpeg") > 0) This.list.add (f); }}} protected void OnDestroy () {Super.ondestroy (); Adapter.cancelalltasks ();//End all download tasks when exiting the program}}
2, Photowalladapter adapter
public class Photowalladapter extends arrayadapter<file> implements Onscrolllistener {//Record all tasks being downloaded or waiting to be downloaded 。 Private set<bitmapworkertask> taskcollection; The core class of the image caching technique, used to cache all downloaded images, and//To remove the least recently used images when the program memory reaches the set value. Private lrucache<string, bitmap> Mmemorycache; Instance of the GridView private GridView Mphotowall; The first visible image of the subscript private int mfirstvisibleitem; How many pictures can be seen on a screen private int mvisibleitemcount; Record whether the program was just opened to solve the problem of entering the program without scrolling the screen and not downloading the picture. Private Boolean isfirstenter = true; arraylist<file> list = null; Public Photowalladapter (context context, int Textviewresourceid, arraylist<file> objects, GridView Photow All) {Super (context, Textviewresourceid, objects); Mphotowall = Photowall; List = objects; Taskcollection = new hashset<bitmapworkertask> (); Gets the application maximum available memory int maxmemory = (int) runtime.getruntime (). MaxMemory (); int cacheSize = MAXMEMORY/8; Set Picture Ease1/8 Mmemorycache = new lrucache<string, bitmap> (cacheSize) {@Override Pro for the maximum available memory size of the program tected int sizeOf (String key, Bitmap Bitmap) {return bitmap.getbytecount (); } }; Mphotowall.setonscrolllistener (this); Public View GetView (int position, View Convertview, ViewGroup parent) {final File url = getItem (position); View view; if (Convertview = = null) {view = Layoutinflater.from (GetContext ()). Inflate (r.layout.photo_ layout, NULL); } else {view = Convertview; } final ImageView photo = (ImageView) View.findviewbyid (R.id.photo); Set a tag for ImageView to ensure that the image is loaded asynchronously without ordering Photo.settag (Url.getabsolutepath ()); Setimageview (Url.getabsolutepath (), photo); return view; }/** * Set picture for ImageView. First, remove the cache of the image from the LRUCache and set it to ImageView. If there is no cache for the picture in LRUCache, * set a default picture for ImageView. * @param IMAGEURL * The URL address of the picture to use as the key for the LRUCache. * @param ImageView * controls for displaying pictures. */private void Setimageview (String imageUrl, ImageView ImageView) {Bitmap Bitmap = Getbitmapfrommemorycache (im Ageurl); if (bitmap! = null) {Imageview.setimagebitmap (bitmap); } else {bitmap=getloacalbitmap (IMAGEURL); Imageview.setimageresource (R.drawable.empty_photo); }}/** * Store a picture in the LRUCache. * @param key * LRUCache, where the URL of the image is passed in. * @param bitmap * LRUCache key, where bitmap objects downloaded from the network are passed in. */@SuppressLint ("Newapi") public void Addbitmaptomemorycache (String key, Bitmap Bitmap) {if (Getbitmapfrommemor Ycache (key) = = null) {Mmemorycache.put (key, bitmap); }}/** * Gets a picture from LRUCache and returns null if it does not exist. * @param key * LRUCache, where the URL of the image is passed in. * @return The Bitmap object that corresponds to the incoming key, or null. */@SuppressLint ("Newapi") public Bitmap GetbitmapfromMemoryCache (String key) {return mmemorycache.get (key); } @Override public void onscrollstatechanged (Abslistview view, int scrollstate) {//Only when the GridView is stationary to download the picture, the Grid When the view is sliding, cancel all tasks that are being downloaded if (scrollstate = = Scroll_state_idle) {loadbitmaps (Mfirstvisibleitem, Mvisibleitemco UNT); } else {cancelalltasks (); }} @Override public void onscroll (Abslistview view, int firstvisibleitem, int visibleitemcount, int t Otalitemcount) {mfirstvisibleitem = Firstvisibleitem; Mvisibleitemcount = VisibleItemCount; The downloaded task should be called by onscrollstatechanged, but Onscrollstatechanged will not be called when the program is first entered,//So the download task is started here for the first entry program. if (isfirstenter && visibleitemcount > 0) {loadbitmaps (Firstvisibleitem, VisibleItemCount); Isfirstenter = false; }}/** * Loads the bitmap object. This method checks the ImageView bitmap object visible in all screens in LRUCache, and if any ImageView bitmap object is found not in the cache, the asynchronous thread is opened to download the image. * * @param Firstvisibleitem * The first visible imageview subscript * @param visibleitemcount * Total visible in the screen Number of elements */private void loadbitmaps (int firstvisibleitem, int visibleitemcount) {try {for (int i = Firstvisibleitem; I < Firstvisibleitem + VisibleItemCount; i++) {String imageUrl = List.get (i). GetAbsolutePath (); Bitmap Bitmap = Getbitmapfrommemorycache (IMAGEURL); if (bitmap = = null) {//If the cache does not have bitmapworkertask task = new Bitmapworkertask (); Taskcollection.add (Task); Task.execute (IMAGEURL);//Perform an asynchronous task and pass in the loaded Picture URL address (here is the picture on the SD card)} else {ImageView ImageView = (ImageView) Mphotowall. Findviewwithtag (IMAGEURL); if (ImageView! = null && bitmap! = null) {Imageview.setimagebitmap (bitmap); } }}} catch (Exception e) {e.printstacktrace (); }}/** * Cancels all tasks that are downloading or waiting to be downloaded. */public void Cancelalltasks () {if (taskcollection! = null) {for (Bitmapworkertask Task:taskcoll ection) {Task.cancel (false); }}}/** * The task of downloading pictures asynchronously. */class Bitmapworkertask extends Asynctask<string, Void, bitmap> {/** * image URL Address */ Private String ImageUrl; @Override protected Bitmap doinbackground (String ... params) {imageUrl = params[0]; Start downloading pictures in the background Bitmap Bitmap = Getloacalbitmap (Params[0]); if (bitmap! = null) {//The picture is downloaded and cached to Lrccache Addbitmaptomemorycache (Params[0], bitmap); } return bitmap; } @Override protected void OnPostExecute (Bitmap Bitmap) {super.onpostexecute (BITMAP); According to tag find the correspondingThe ImageView control that displays the downloaded picture. ImageView ImageView = (ImageView) mphotowall. Findviewwithtag (IMAGEURL); if (ImageView! = null && bitmap! = null) {Imageview.setimagebitmap (bitmap); } taskcollection.remove (this); }} private Bitmap getloacalbitmap (String url) {try {FileInputStream FIS = new FileInputStream ( URL); Return Bitmapfactory.decodestream (FIS); /Turn the flow into bitmap picture} catch (FileNotFoundException e) {e.printstacktrace (); return null; } }}
To learn more about the small partners, you can click to view the source code , run the test yourself.
Inquiries or technical exchanges, please join the official QQ Group: (452379712)
Jerry Education
Source:http://blog.csdn.net/jerehedu/
This article is the copyright of Yantai Jerry Education Technology Co., Ltd. and CSDN Common, welcome reprint, but without the author's consent must retain this paragraph statement, and in the article page obvious location to the original link, otherwise reserves the right to pursue legal responsibility.
Android Batch Image load Classic series--use LRUCache, Asynctask cache and load images asynchronously