Android 实现异步加载图片

大鹏一日同风起,扶摇直上九万里。这篇文章主要讲述Android 实现异步加载图片相关的知识,希望能为你提供帮助。
麦洛开通博客以来,有一段时间没有更新博文了.主要是麦洛这段时间因项目开发实在太忙了.今天周六还在公司加班,苦逼程序猿都是这样生活的.
今天在做项目的时候,有一个实现异步加载图片的功能,虽然比较简单但还是记录一下吧.因为麦洛之前实现异步加载图片都是使用了AsynTask这个API,继续这个类,实现起来非常简单也很方便.在doInBackground()方法里实现下载逻辑.具体实现如下
实现逻辑是:先从内存中读取,如果内存中有这张图片,则直接使用; 如果内存没有再到sdcard上读取,如果有则显示; 如果sdcard上还没有则到网络上读取.内存中开启缓存是参考了网上的实现.麦洛在这里非常感谢喜欢分享的程序猿们.

Android 实现异步加载图片

文章图片

public  class  ImageDownloader  extends  AsyncTask< String,  Integer,  Object>   {        private  static  final  String  TAG  =  "ImageDownloader";         //  为了加快速度,在内存中开启缓存(主要应用于重复图片较多时,或者同一个图片要多次被访问,比如在ListView时来回滚动)         private  Map< String,  SoftReference< Drawable> >   imageCache  =  new  HashMap< String,  SoftReference< Drawable> > ();         /**           *  显示图片的控件          */         private  ImageView  mImageView;         public  ImageDownloader(ImageView  image)  {                 mImageView  =  image;         }        @Override        protected  void  onPreExecute()  {                super.onPreExecute();         }        @Override        protected  Object  doInBackground(String...  params)  {                //  Log.i("ImageDownloader",  "loading  image...");                 String  url  =  params[0];                 Drawable  drawable  =  null;                 try  {                        if  (!"".equals(url)  & &   url  !=  null)  {                                 String  fileName  =  url.hashCode()+".jpg";                                 //  如果缓存过就从缓存中取出数据                                 if  (imageCache.containsKey(fileName))  {                                         SoftReference< Drawable>   softReference  =  imageCache.get(fileName);                                         drawable  =  softReference.get();                                         if  (drawable  !=  null)  {                                                return  drawable;                                         }                                 }                                 File  dir  =  new  File(FileConstant.IMAGE_FILE_PATH);                                 if  (!dir.exists())  {                                        boolean  m  =  dir.mkdirs();                                 }                                 File  file  =  new  File(dir,  fileName);                                 if  (file.exists()  & &   file.length()  >   0)  {                                         Log.i(TAG,  "load  image  from  sd  card");                                         //  如果文件存在则直接读取sdcard                                         drawable  =  readFromSdcard(file);                                 }  else  {                                        //file.createNewFile();                                         Log.i(TAG,  "load  image  from  network");                                         URL  imageUrl  =  new  URL(url);                                         //  写入sdcard                                         if  (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))  {                                                 saveImageFile(imageUrl,  file);                                                 drawable  =  Drawable.createFromStream(new  FileInputStream(file),  fileName);                                         }else{                                                //直接从流读取                                                 drawable  =  Drawable.createFromStream(imageUrl.openStream(),  fileName);                                         }                                 }                                if(drawable!=null){                                        //保存在缓存中                                         imageCache.put(fileName,  new  SoftReference< Drawable> (drawable));                                 }                         }                 }  catch  (Exception  e)  {                         e.printStackTrace();                 }                  return  drawable;         }        /**           *  save  image*/         private  void  saveImageFile(URL  url,  File  file)  {                 FileOutputStream  out  =  null;                 InputStream  in  =  null;                 try  {                         file.deleteOnExit();                         out  =  new  FileOutputStream(file);                         in  =  url.openStream();                         byte[]  buf  =  new  byte[1024];                         int  len  =  -1;                         while((len  =  in.read(buf))!=-1){                                 out.write(buf,  0,  len);                                 out.flush();                         }                 }  catch  (Exception  e)  {                         e.printStackTrace();                 }  finally  {                        if(out!=null){                                try  {                                         out.close();                                 }  catch  (IOException  e)  {                                         e.printStackTrace();                                 }                         }                        if(in!=null){                                try  {                                         in.close();                                 }  catch  (IOException  e)  {                                         e.printStackTrace();                                 }                         }                 }         }        /**           *  从sdcard中获取图片*/         private  Drawable  readFromSdcard(File  file)  throws  Exception  {                 FileInputStream  in  =  new  FileInputStream(file);                 return  Drawable.createFromStream(in,  file.getName());         }        @Override        protected  void  onPostExecute(Object  result)  {                super.onPostExecute(result);                 Drawable  drawable  =  (Drawable)  result;                 if  (mImageView  !=  null  & &   drawable  !=  null)  {                         mImageView.setBackgroundDrawable(drawable);                 }         }        @Override        protected  void  onProgressUpdate(Integer...  values)  {                super.onProgressUpdate(values);         }        @Override        protected  void  onCancelled()  {                super.onCancelled();         }}

Android 实现异步加载图片

文章图片

使用时:
ImageDownloader  loader  =  new  ImageDownloader(imageView); loader.execute(url);

其实这样的话,还有一些隐患的,就是说这个类实现还是有些问题的.比如每次都在imageView中设置网络上的图片时,其实是没有使用到这个类里面的内存缓存的,就是imageCache
Map< String,  SoftReference< Drawable> >   imageCache  =  new  HashMap< String,  SoftReference< Drawable> > ();

因为每次设置imageView的时候,都是new了一个ImageDownloader的对象.所以每个ImageDownloader对象里面都是独立的一个imageCache.
      另外,AsynTask也是一个线程.而每次使用都开一个线程来load 图片,对线程个数没有进行显示,毕竟线程数目还是有限制的.
所以麦洛今天发现了这个问题,于是参考了别人的实现,使用了线程池,实现逻辑也上面的代码一样,先从内存读取,如果没有到sdcard读取,如果还是没有,则是网络读取; 实现没有使用AsynTask,具体代码如下:
Android 实现异步加载图片

文章图片

/**   *  异步加载图片,并将图片设置到ImageView控件中*/public  class  ImageDownloader  extends  AsyncTask< String,  Integer,  Object>   {        private  static  final  String  TAG  =  "ImageDownloader";         //  为了加快速度,在内存中开启缓存(主要应用于重复图片较多时,或者同一个图片要多次被访问,比如在ListView时来回滚动)         private  Map< String,  SoftReference< Drawable> >   imageCache  =  new  HashMap< String,  SoftReference< Drawable> > ();         /**           *  显示图片的控件          */         private  ImageView  mImageView;         public  ImageDownloader(ImageView  image)  {                 mImageView  =  image;         }        @Override        protected  void  onPreExecute()  {                super.onPreExecute();         }        @Override        protected  Object  doInBackground(String...  params)  {                //  Log.i("ImageDownloader",  "loading  image...");                 String  url  =  params[0];                 Drawable  drawable  =  null;                 try  {                        if  (!"".equals(url)  & &   url  !=  null)  {                                 String  fileName  =  url.hashCode()+".jpg";                                 //  如果缓存过就从缓存中取出数据                                 if  (imageCache.containsKey(fileName))  {                                         SoftReference< Drawable>   softReference  =  imageCache.get(fileName);                                         drawable  =  softReference.get();                                         if  (drawable  !=  null)  {                                                return  drawable;                                         }                                 }                                 File  dir  =  new  File(FileConstant.IMAGE_FILE_PATH);                                 if  (!dir.exists())  {                                        boolean  m  =  dir.mkdirs();                                 }                                 File  file  =  new  File(dir,  fileName);                                 if  (file.exists()  & &   file.length()  >   0)  {                                         Log.i(TAG,  "load  image  from  sd  card");                                         //  如果文件存在则直接读取sdcard                                         drawable  =  readFromSdcard(file);                                 }  else  {                                        //file.createNewFile();                                         Log.i(TAG,  "load  image  from  network");                                         URL  imageUrl  =  new  URL(url);                                         //  写入sdcard                                         if  (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))  {                                                 saveImageFile(imageUrl,  file);                                                 drawable  =  Drawable.createFromStream(new  FileInputStream(file),  fileName);                                         }else{                                                //直接从流读取                                                 drawable  =  Drawable.createFromStream(imageUrl.openStream(),  fileName);                                         }                                 }                                if(drawable!=null){                                        //保存在缓存中                                         imageCache.put(fileName,  new  SoftReference< Drawable> (drawable));                                 }                         }                 }  catch  (Exception  e)  {                         e.printStackTrace();                 }                  return  drawable;         }        /**           *  save  image*/         private  void  saveImageFile(URL  url,  File  file)  {                 FileOutputStream  out  =  null;                 InputStream  in  =  null;                 try  {                         file.deleteOnExit();                         out  =  new  FileOutputStream(file);                         in  =  url.openStream();                         byte[]  buf  =  new  byte[1024];                         int  len  =  -1;                         while((len  =  in.read(buf))!=-1){                                 out.write(buf,  0,  len);                                 out.flush();                         }                 }  catch  (Exception  e)  {                         e.printStackTrace();                 }  finally  {                        if(out!=null){                                try  {                                         out.close();                                 }  catch  (IOException  e)  {                                         e.printStackTrace();                                 }                         }                        if(in!=null){                                try  {                                         in.close();                                 }  catch  (IOException  e)  {                                         e.printStackTrace();                                 }                         }                 }         }        /**           *  从sdcard中获取图片    */         private  Drawable  readFromSdcard(File  file)  throws  Exception  {                 FileInputStream  in  =  new  FileInputStream(file);                 return  Drawable.createFromStream(in,  file.getName());         }        @Override        protected  void  onPostExecute(Object  result)  {                super.onPostExecute(result);                 Drawable  drawable  =  (Drawable)  result;                 if  (mImageView  !=  null  & &   drawable  !=  null)  {                         mImageView.setBackgroundDrawable(drawable);                 }         }        @Override        protected  void  onProgressUpdate(Integer...  values)  {                super.onProgressUpdate(values);         }        @Override        protected  void  onCancelled()  {                super.onCancelled();         }}

Android 实现异步加载图片

文章图片

这个ImageDownloader2的使用也很简单
Android 实现异步加载图片

文章图片

public  class  ImageUtil  {        /**           *  image  loader          */         static  ImageDownloader2  loader  =  null;                 /**           *  load  image*/         public  static  void  loadImage(String  url,final  ImageView  imageView){                if(loader  ==  null){                         loader  =  new  ImageDownloader2();                 }                 loader.loadDrawable(url,  new  ImageCallback()  {                                                 @Override                        public  void  imageLoaded(Drawable  imageDrawable)  {                                if(imageDrawable!=null){                                         imageView.setBackgroundDrawable(imageDrawable);                                 }                         }                 });         }         }

Android 实现异步加载图片

文章图片

每次在使用是需要调用ImageUtil.loadImage(url,imageView)将图片url已经需要显示图片的控件ImageView的引用传入就可以了.
 
【Android 实现异步加载图片】


    推荐阅读