全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

Android实现异步加载图片

麦洛开通博客以来,有一段时间没有更新博文了.主要是麦洛这段时间因项目开发实在太忙了.今天周六还在公司加班,苦逼程序猿都是这样生活的.

今天在做项目的时候,有一个实现异步加载图片的功能,虽然比较简单但还是记录一下吧.因为麦洛之前实现异步加载图片都是使用了AsynTask这个API,继续这个类,实现起来非常简单也很方便.在doInBackground()方法里实现下载逻辑.具体实现如下

实现逻辑是:先从内存中读取,如果内存中有这张图片,则直接使用;如果内存没有再到sdcard上读取,如果有则显示;如果sdcard上还没有则到网络上读取.内存中开启缓存是参考了网上的实现.麦洛在这里非常感谢喜欢分享的程序猿们.

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();
  }

}

使用时:

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,具体代码如下:

/**
 * 异步加载图片,并将图片设置到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();
  }

}

这个ImageDownloader2的使用也很简单

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);
        }
      }
    });
  }
  
}

每次在使用是需要调用ImageUtil.loadImage(url,imageView)将图片url已经需要显示图片的控件ImageView的引用传入就可以了.

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# Android异步加载图片  # Android异步加载  # Android加载图片  # Android使用AsyncTask加载图片的操作流程  # Android实现网络加载图片点击大图后浏览可缩放  # android中Glide实现加载图片保存至本地并加载回调监听  # Android中Glide加载图片并实现图片缓存  # Android不压缩图片实现高清加载巨图实例  # 都是  # 也很  # 加载  # 要多  # 应用于  # 如在  # 使用了  # 在这里  # 都在  # 还在  # 则是  # 中有  # 这个问题  # 这段  # 这张  # 并将  # 如果没有  # 实在太  # 再到  # 还有一些 


相关文章: 制作ppt免费网站有哪些,有哪些比较好的ppt模板下载网站?  建站之星如何快速更换网站模板?  建站主机服务器选购指南:轻量应用与VPS配置解析  建站主机空间推荐 高性价比配置与快速部署方案解析  网站制作网站,深圳做网站哪家比较好?  如何在Golang中指定模块版本_使用go.mod控制版本号  佛山企业网站制作公司有哪些,沟通100网上服务官网?  制作网站怎么制作,*游戏网站怎么搭建?  购物网站制作公司有哪些,哪个购物网站比较好?  制作旅游网站html,怎样注册旅游网站?  移民网站制作流程,怎么看加拿大移民官网?  阿里云网站搭建费用解析:服务器价格与建站成本优化指南  个人摄影网站制作流程,摄影爱好者都去什么网站?  如何在沈阳梯子盘古建站优化SEO排名与功能模块?  如何在云服务器上快速搭建个人网站?  专业网站设计制作公司,如何制作一个企业网站,建设网站的基本步骤有哪些?  如何打造高效商业网站?建站目的决定转化率  网页设计与网站制作内容,怎样注册网站?  微信小程序 input输入框控件详解及实例(多种示例)  中山网站制作网页,中山新生登记系统登记流程?  如何批量查询域名的建站时间记录?  制作网站的软件下载免费,今日头条开宝箱老是需要下载怎么回事?  c# Task.Yield 的作用是什么 它和Task.Delay(1)有区别吗  宁波免费建站如何选择可靠模板与平台?  安徽网站建设与外贸建站服务专业定制方案  一键网站制作软件,义乌购一件代发流程?  厦门模型网站设计制作公司,厦门航空飞机模型掉色怎么办?  相亲简历制作网站推荐大全,新相亲大会主持人小萍萍资料?  python的本地网站制作,如何创建本地站点?  建站之星安装模板失败:服务器环境不兼容?  建站之星代理平台如何选择最佳方案?  云南网站制作公司有哪些,云南最好的招聘网站是哪个?  江苏网站制作公司有哪些,江苏书法考级官方网站?  制作网站哪家好,cc、.co、.cm哪个域名更适合做网站?  如何选择高性价比服务器搭建个人网站?  详解免费开源的DotNet二维码操作组件ThoughtWorks.QRCode(.NET组件介绍之四)  导航网站建站方案与优化指南:一站式高效搭建技巧解析  名字制作网站免费,所有小说网站的名字?  如何制作网站标识牌,动态网站如何制作(教程)?  如何注册花生壳免费域名并搭建个人网站?  西安市网站制作公司,哪个相亲网站比较好?西安比较好的相亲网站?  昆明高端网站制作公司,昆明公租房申请网上登录入口?  小视频制作网站有哪些,有什么看国内小视频的网站,求推荐?  微信网站制作公司有哪些,民生银行办理公司开户怎么在微信网页上查询进度?  制作网站建设的公司有哪些,网站建设比较好的公司都有哪些?  如何用AWS免费套餐快速搭建高效网站?  北京网站制作的公司有哪些,北京白云观官方网站?  广州顶尖建站服务:企业官网建设与SEO优化一体化方案  如何通过FTP空间快速搭建安全高效网站?  如何快速搭建高效WAP手机网站? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。