Android realizes picture caching and asynchronous loading _android

Source: Internet
Author: User

ImageManager2 This class has asynchronous download pictures from the network, from the SD to read local pictures, memory cache, hard disk cache, pictures using animation and other functions, has been applied in a large number of applications in the picture for more than a year, there is no oom.

Android programs often overflow with memory, and there are many solutions on the web, such as soft references, manual calls to recycle, and so on. But after our practice found that these programs, did not have a good effect, our application will still appear a lot of oom, especially our application contains a large number of pictures. Soft references are largely invalidated after android3.0, because the virtual machines are recycled as long as they touch a soft reference, so they don't bring any performance improvements.

My solution here is the Handlerthread (asynchronous load) +lrucache (memory cache) +disklrucache (hard disk cache).

As a programmer, I do not say much, directly with everyone to share my code, the use of code to communicate more convenient.

Package com.example.util;
Import Java.io.File;
Import Java.util.Iterator;
Import java.util.LinkedList;
Import Java.util.Queue;
 
Import Java.util.Stack;
Import org.apache.http.HttpEntity;
Import Org.apache.http.HttpResponse;
Import Org.apache.http.client.methods.HttpGet;
 
Import Org.apache.http.util.EntityUtils;
Import Android.app.ActivityManager;
Import Android.content.Context;
Import Android.graphics.Bitmap;
Import Android.graphics.BitmapFactory;
Import android.graphics.drawable.BitmapDrawable;
Import android.graphics.drawable.ColorDrawable;
Import android.graphics.drawable.Drawable;
Import android.graphics.drawable.TransitionDrawable;
Import Android.media.ThumbnailUtils;
Import Android.os.Handler;
Import Android.os.HandlerThread;
Import Android.os.Looper;
Import Android.os.Message;
Import Android.support.v4.util.LruCache;
 
Import Android.widget.ImageView;
 
Import com.example.MyApplication; /** * Picture Loading class * * @author month bird/public class ImageManager2 {private static imagEManager2 Imagemanager;
  Public lrucache<string, bitmap> Mmemorycache; private static final int disk_cache_size = 1024 * 1024 * 20;
  10MB private static final String Disk_cache_subdir = "thumbnails";
  Public Disklrucache Mdiskcache;
 
  private static MyApplication MyApp;
 
  /** picture load Queue, LIFO * * Private stack<imageref> Mimagequeue = new stack<imageref> (); /** Picture request queue, advanced first out, used to store sent requests.
 
  * Private queue<imageref> Mrequestqueue = new linkedlist<imageref> ();
 
  /** picture loading thread Message Processor/private Handler Mimageloaderhandler;
 
  /** picture load thread is ready */private Boolean mimageloaderidle = true;
  /** Request Picture * * private static final int msg_request = 1;
  /** Picture Loading Complete * * private static final int msg_reply = 2;
  /** Abort picture load thread/private static final int msg_stop = 3;
 
  /** if the picture is loaded from the network, then the fade animation is applied, and if you read from the cache you do not apply the animation/private Boolean isfromnet = true;
   /** * Gets a single instance that can only be used in the UI thread. * * @param context * @return/public static ImageManager2 fromContext) {//If not in the UI thread, throws an exception if (Looper.mylooper ()!= looper.getmainlooper ()) {throw new Runtimeexceptio
    N ("Cannot instantiate outside UI thread.");
    } if (MyApp = = null) {MyApp = (MyApplication) context.getapplicationcontext ();
    } if (Imagemanager = = null) {Imagemanager = new ImageManager2 (MyApp);
  return imagemanager;  /** * Private constructor, guaranteed single case mode * * @param context/Private ImageManager2 (context) {int memclass =
    ((Activitymanager) context. Getsystemservice (Context.activity_service)). Getmemoryclass (); Memclass = memclass > 32?
    32:memclass;
 
    Use 1/8 of available memory as a picture cache final int cacheSize = 1024 * 1024 * MEMCLASS/8;
        Mmemorycache = new lrucache<string, bitmap> (cacheSize) {protected int sizeOf (String key, Bitmap Bitmap) {
      return Bitmap.getrowbytes () * Bitmap.getheight ();
 
    }
 
    }; File Cachedir = Disklrucache. Getdiskcachedir (ContexT, Disk_cache_subdir);
 
  Mdiskcache = Disklrucache.opencache (Context, Cachedir, disk_cache_size);
    /** * Store picture information */class Imageref {/** picture corresponding ImageView control * * ImageView ImageView;
    /** Image URL Address * * String URL;
    /** Picture Cache Path */String FilePath;
    /** Default Graph Resource ID */int resid;
    int width = 0;
 
    int height = 0; /** * constructor * @param imageview * @param URL * @param resid * @param filePath * *
      Mageref (ImageView imageview, string url, string filePath, int resid) {this.imageview = ImageView;
      This.url = URL;
      This.filepath = FilePath;
    This.resid = Resid; Imageref (ImageView imageview, string url, string filePath, int resid, int width, int height) {this.
      ImageView = ImageView;
      This.url = URL;
      This.filepath = FilePath;
      This.resid = Resid;
      This.width = width;
    This.height = height; }/** * Display picture * * @param imagEview * @param URL * @param resid/public void DisplayImage (ImageView imageview, String url, int resid) {
    if (ImageView = = null) {return;
    } if (Imageview.gettag ()!= null && imageview.gettag (). toString (). Equals (URL)) {return;
      } if (resid >= 0) {if (imageview.getbackground () = = null) {Imageview.setbackgroundresource (RESID);
 
    } imageview.setimagedrawable (NULL);
    } if (url = null | | url.equals ("")) {return;
 
    //Add URL tag imageview.settag (URL);
    Read Map cache Bitmap Bitmap = mmemorycache.get (URL);
      if (bitmap!= null) {Setimagebitmap (ImageView, Bitmap, false);
    Return
    }//Generate filename String filePath = urltofilepath (URL);
    if (FilePath = = null) {return;
  } queueimage (New Imageref (ImageView, URL, FilePath, resid)); /** * Display picture fixed size picture thumbnail, generally used to display the picture of the list, can greatly reduce memory use * * @param imageview load the picture's control * @param URL Load address * @param resid default picture * @param width Specifies the height * @param height Specifies the altitude * * public void displayimage (ImageView ima
    Geview, String url, int resid, int width, int height) {if (ImageView = null) {return; } if (resid >= 0) {if (imageview.getbackground () = = null) {Imageview.setbackgroundresource (RESID)
      ;
 
    } imageview.setimagedrawable (NULL);
    } if (url = null | | url.equals ("")) {return;
    //Add URL tag imageview.settag (URL);
    Read Map cache Bitmap Bitmap = mmemorycache.get (url + width + height);
      if (bitmap!= null) {Setimagebitmap (ImageView, Bitmap, false);
    Return
    }//Generate filename String filePath = urltofilepath (URL);
    if (FilePath = = null) {return;
  } queueimage (New Imageref (ImageView, URL, FilePath, resid, width, height)); /** * Team, LIFO * * @param imageref/public void Queueimage (Imageref imageref) {//delete Imagevi
 ew   Iterator<imageref> iterator = Mimagequeue.iterator ();
      while (Iterator.hasnext ()) {if (Iterator.next (). ImageView = = Imageref.imageview) {iterator.remove ();
    }//Add request Mimagequeue.push (IMAGEREF);
  SendRequest (); /** * Send request */private void SendRequest () {//Open picture load thread if (Mimageloaderhandler = null) {Ha
      Ndlerthread Imageloader = new Handlerthread ("Image_loader");
      Imageloader.start ();
    Mimageloaderhandler = new Imageloaderhandler (Imageloader.getlooper ()); ///Send request if (Mimageloaderidle && mimagequeue.size () > 0) {imageref imageref = Mimagequeue.pop
      ();
      Message message = Mimageloaderhandler.obtainmessage (Msg_request, imageref);
      Mimageloaderhandler.sendmessage (message);
      Mimageloaderidle = false;
    Mrequestqueue.add (IMAGEREF); }/** * Picture load thread/class Imageloaderhandler extends Handler {public ImagelOaderhandler (Looper looper) {super (Looper);
 
      Handlemessage (Message msg) {if (msg = null) return;
        Switch (msg.what) {case Msg_request://Receive request Bitmap Bitmap = null;
        Bitmap tbitmap = null;
          if (msg.obj!= null && msg.obj instanceof imageref) {imageref imageref = (imageref) msg.obj;
          String url = imageref.url;
          if (url = null) return;
            If the local URL reads an SD photo album, read directly without passing through DiskCache if (Url.tolowercase (). Contains ("DCIM")) {tbitmap = null;
            Bitmapfactory.options opt = new bitmapfactory.options ();
            Opt.insamplesize = 1;
            Opt.injustdecodebounds = true;
            Bitmapfactory.decodefile (URL, opt);
            int bitmapsize = opt.outheight * Opt.outwidth * 4;
            Opt.insamplesize = bitmapsize/(1000 * 2000);
            Opt.injustdecodebounds = false; Tbitmap = Bitmapfactory.DecodeFile (URL, opt); 
                  if (imageref.width!= 0 && imageref.height!= 0) {bitmap = Thumbnailutils.extractthumbnail (Tbitmap,
              Imageref.width, Imageref.height, thumbnailutils.options_recycle_input);
            Isfromnet = true;
              else {bitmap = Tbitmap;
            Tbitmap = null;
 
          } else Bitmap = Mdiskcache.get (URL);
            if (bitmap!= null) {//ToolUtil.log (read from disk cache);  Write to the map cache if (imageref.width!= 0 && imageref.height!= 0) {if mmemorycache.get (URL +
                    Imageref.width + imageref.height) = = null) mmemorycache.put (URL + imageref.width
            + Imageref.height, bitmap);
            else {if (mmemorycache.get (URL) = null) mmemorycache.put (URL, bitmap);
 }} else {try {             byte[] data = loadbytearrayfromnetwork (URL);
                if (data!= null) {bitmapfactory.options opt = new bitmapfactory.options ();
 
                Opt.insamplesize = 1;
                Opt.injustdecodebounds = true;
                Bitmapfactory.decodebytearray (data, 0, data.length, opt);
                      int bitmapsize = opt.outheight * Opt.outwidth * 4;//pixels*3 if it ' s RGB and pixels*4
                If it ' s ARGB if (bitmapsize > 1000 * 1200) opt.insamplesize = 2;
                Opt.injustdecodebounds = false;
                Tbitmap = Bitmapfactory.decodebytearray (data, 0, data.length, opt);
                      if (imageref.width!= 0 && imageref.height!= 0) {bitmap = Thumbnailutils
             . Extractthumbnail (Tbitmap, Imageref.width,             Imageref.height, Thumbnailutils.options_recycle_input);
                  else {bitmap = Tbitmap;
                Tbitmap = null; } if (bitmap!= null && URL!= null) {//write SD card if (imageref . width!= 0 && imageref.height!= 0) {mdiskcache.put (URL + imageref.wid
                    th + imageref.height, bitmap);
                  Mmemorycache.put (url + imageref.width + imageref.height, bitmap);
                    else {mdiskcache.put (URL, bitmap);
                  Mmemorycache.put (URL, bitmap);
                } isfromnet = true; '} ' catch (OutOfMemoryError e) {}}} if (Mimagem Anagerhandler!= null) {Message message = MimagemanagErhandler.obtainmessage (msg_reply, bitmap);
        Mimagemanagerhandler.sendmessage (message);
 
      } break;
        Case MSG_STOP://Receive termination instruction Looper.mylooper (). Quit ();
 
      Break /** UI Thread Message Processor */private Handler Mimagemanagerhandler = new Handler () {@Override public void
 
          Handlemessage (msg) {if (msg!= null) {switch (msg.what) {case msg_reply://Receive Answer
 
            do {imageref imageref = Mrequestqueue.remove ();
 
            if (imageref = null) break; if (Imageref.imageview = null | | IMAGEREF.IMAGEVIEW.GETTAG () = NULL | | imageref.url = n
 
            ull) break; if (!) ( Msg.obj instanceof Bitmap) | |
            Msg.obj = = null) {break;
 
            } Bitmap Bitmap = (Bitmap) msg.obj; Not the same imageview if (!) ( Imageref.url). Equals ((String) Imageref.imagevIew. Gettag ()) {break;
            } setimagebitmap (Imageref.imageview, Bitmap, isfromnet);
 
          Isfromnet = false;
 
          } while (false);
        Break
 
      }//Set idle flag Mimageloaderidle = true;
      If the service is not closed, the next request is sent.
      if (Mimageloaderhandler!= null) {SendRequest ();
 
  }
    }
  };
    /** * Add picture Display fade animation * */private void Setimagebitmap (ImageView imageview, Bitmap Bitmap, Boolean Istran) {  if (Istran) {final transitiondrawable td = New Transitiondrawable (new drawable[] {new Colordrawable (Android.
      r.color.transparent), New Bitmapdrawable (bitmap)});
      Td.setcrossfadeenabled (TRUE);
      Imageview.setimagedrawable (TD);
    Td.starttransition (300);
    else {imageview.setimagebitmap (bitmap); /** * Get picture byte array from network * * @param URL * @return/private byte[] Loadbytearrayfromnetwork (String URL) {try {HttpGet method = new HttpGet (URL);
      HttpResponse response = Myapp.gethttpclient (). Execute (method);
      httpentity entity = response.getentity ();
 
    return Entityutils.tobytearray (entity);
    catch (Exception e) {return null; 
 
    /** * Generates cached file full pathname based on URL * * @param URL * @return/public string Urltofilepath (string url) {
    Extension position int index = Url.lastindexof ('. ');
    if (index = = 1) {return null;
 
    } StringBuilder FilePath = new StringBuilder ();
 
    Picture Access Path Filepath.append (Myapp.getcachedir (). toString ()). Append ('/'); Picture filename Filepath.append (MD5.
 
    Md5 (URL)). Append (url.substring (index));
  return filepath.tostring ();
   After/** * Activity#onstop, ListView will not have any residual requests.
 
  */public void Stop () {//Empty request queue mimagequeue.clear ();
 }
 
}

Here is a solution for asynchronous loading, memory caching, and hard disk caching, which I hope will be helpful to our learning.

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.