Foreword
In fact, I am very lucky. After one week of entry, I can follow the two brothers to develop Android. My brother is a great god. As Xiaobai, I can only learn more and work hard. Recently, I have been busy with a chance to summarize. Today, I just completed the class that the Android client picture is not loaded asynchronous. Here is a record (PS: Actually, I refer to online open source implementation)
principle
The principles of loading pictures in ListView or GridView are basically the same:
Get it from the memory cache, and return it. If you cannot get the next step from the file cache, you will return and update to the memory cache. If you cannot get it Memory cache and file cache
The flowchart is as follows:
At the same time, pay attention to the number of threads. Generally, loading pictures in ListView, everyone opens new threads to load, but when it is quickly sliding, it is easy to cause OOM, so the number of threads needs to be controlled. We can control the number of threads through the thread pool.
The method of establishing a thread pool is as follows:
ExecutorService Executorservice = Executors.netfixedthreadPool (5); // 5 is variable
File cache class
Import java.io.file; Import Android.Content.Context; Public Class FileCache {Private Static FINAL String Dir_name = "Your_dir"; IR; Public Filecache (Context Context) {// Find The Directory to Save Cached Images If ( Android.OS.environment.GeteXternalstorageState (). Equals (android.os.environment.Media_moundted) {Cachedir = New File textalStoragedirectory (), DIR_NAME);} else {cachedir = context.getCachedir () ;} if (! Cachedir.exist ()) {cachedir.mkders ();}} Public File Getfile (String URL) {// Identify Images by URL's Hash Code String Filename = String.valueof (url.hashcode ()); File f = new file (CacheDir, Filename); Return f;} Public void Clear () {Files = CacheDir.listFiles (); if (files == null) {Return;} ELSE { For (file f: files) {f.delete ();}}}} Memory cache class
Here is a soft reference, map <string, softReference <bitmap >> cache, you can google to a soft reference mechanism. Simply put: MAP is implemented. At the same time
Import java.lang.ref.softReference; Import Java.util.Collections; Import Java.util.linkedhashmap; Import java.util.map; s.Bitmap; Public Class MemoryCache {Private Map <string, Softreference <Bitmap> > Cache = Collections. SynchronizeDMap (New Linkedhashmap <string, SoftReference <bitmap >> (10, 1.5F, TRUE)); e.containskey (ID)) {Return Null;} Softreference <bitmap> Ref = Cache.get (ID); Return Ref.get ();} Public Void Put (String ID, Bitmap Bitmap) {Cache.put (ID, New SoftReference <Bit map> (bitmap);} Public void clear () {cache.clear ();}}Picture loading class
Import java.io.file; Import java.io.fileInputStream; Import java.filenotFoundexception; Import java.fileoutPutstream; ream; Import Java.io.outPutstream; Import Java.net.httpurlConnection; Import java.net.url; Import java.util.Collections; Import Java.util.map; Import Java.util.weakhashmap; Import e; E; MPORT JAVA.UTIL.CURRENT.EXECUTORS; Import android.Content. Context; Import Android.graphics.bitmap; Import Android.graphics.BitmapFactory; Import Android.os.handler; Import Android.Widget.imagevi ew; Public Class ImageLoader { / ** * Network Time Out * / Private Static Final Int Time_out = 30000 ; FINAL Int Thread_num = 5; / ** * Memory Image Cache * / MemoryCache MemoryCache = New MemoryCache (); / ** * File Image Cache * / FileCache FileCache; / ** * Judge image view if it is reuse * / Private Map <IMAGEVIEW, String> Image. Views = Collections. SynchronizeDMap (New Weakhashmap <IMAGEVIEW, String, String > ()); / ** * Thread Pool * / ExecutorService ExecutorService; / ** * Handler to Display Images in UI Thread * / Handler Handler (); Public GELOADER (Context Context) {filecache = new filecache (context );; (Thread_num);} Public Void DisplayImage (Thread_num); put (ImageView, URL); bitmap bitmap = MemoryCache.get (url); if (bitmap! = Null) { // Display IMAGE from Memory Cache ImageView.SetimageBitmap (Bitmap);} Else {// Display from FILE CACHE or Network QueuePhoto (URL, ImageV IEW);}} Private Void QueuePhoto (String URL, ImageView ImageView) {Phototoload PhotoToload = New PHOTOTOLOAD (URL, ImageView); ExecutorService.Submit (New Photosloader (PhotoToload));} Prive Bitmap GetBitmap (String URL) lecache.getFile (url); // From file cache bitmap bmp = decodeFile (f); if (bmp! = NULL) {Return BMP;} // From Network Try {bitmap bitmap = null; url imageurl = new url (url); Next) ImageUrl .opeenconnection (); conn.setConnecttimeout (time_out) ; conn.setReadtimeout (time_out); const.SetinstanceFollowRedirects (true); inputStream is = conn.getinputstream (); am (f); Copystream (is, OS); os.Close (); const.disconnect (conn.disconnect );; Return Bitmap;} Catch (Throwable EX) {if (Exstanceof OutoFMemoryerror) {ClearCache ();} PRIVATE void CopyStream (InputStream is, outputStream OS) {int buffer_size = 1024; Try {byte [] bytes = New Byte [Buffer_size]; While (TRUE) {int count = is.read (bytes, 0, buffer_size); if (count == -1) {Break;} OS.WRI TE (TE bytes, 0, count);}} Catch (Exception E) {}} Private Bitmap DecodeFile (FILE F) {TRY {// TODO: Compress Image Size FileInputstream = NEW FileinputStream (F); bitmap bitmap = bitmapFactory.DecodeStream ( FileInputStream); Return Bitmap;} Catch (FilenotFoundexception E) {Return Null;}} Private void ClearCache () {MemoryCache.clear (); FileCache.c lear ();} /** * task for the queue * * @Author zhengyi .wzy * * */ Private class PhotoToload {Public String url; Public ImageView ImageView; Public PhotoLoad (String URL, ImageView ImageView) {this.url = url; this.imageView = ImageView;} /** * asynchronous to load picking * * @AUTHOR ZHENGYI.WZY * */ Class Photosloader Implements Runnable {PhotoLoad PhotoToload; Public Photosloader (PhotoToload PHOTOTOLOAD) {This.phototoload = Phototoload;} Private Boolean ImageViewReused (PhotoToload PhotoLoad) {String tag = ImageViews.Get (PhotoToload.im.im.im.im.im.im.im.im Ageview) ; if (tag == NULL ||! tag.equals (Phototoload.url)) {Return True;} Return false;} @Override Public Void Run () {// Abort Current Thread if IM Age View REUSED If (ImageViewreused (PhotoToload )) {Return;} bitmap bitmap = getbitmap (Phototoload.url); // Update MemoryCache.put (Phototoload.url, bitmap); if (ImageViewReus ED (PhotoToload)) {Return;} //d't Change UI in Children Thread Bitmapdisplayer BD = New Bitmapdisplayer (Bitmap, PhotoToload); Handler.post (BD);} Class Bitmapdisplayer IMPLEMENTS Runnable {BI TMAP BITMAP; PhotoToload PhotoToload; Public Bitmapdisplayer (bitmap bitmap, Photoload PhotoLoad) {this.bitmap = bitmap; this. PhotoLoad = PHOTOTOLOAD;} @Override Public Void Run () {if (iMageViewReused (PhotoToload)) {Return;} if (bitmap! = NULL) oad.imageView.setImageBitmap (bitmap);} else {PhotoToload.imageView.setImageResource ( Default_bg);}}}}}Call method
ImageLoader ImageLoader = New ImageLoader (Context); ImageLoader.displayImage (ImageUrl, ImageView);