当前位置: 首页 > 编程笔记 >

在Android的应用中实现网络图片异步加载的方法

严亦
2023-03-14
本文向大家介绍在Android的应用中实现网络图片异步加载的方法,包括了在Android的应用中实现网络图片异步加载的方法的使用技巧和注意事项,需要的朋友参考一下

前言
其实很幸运,入职一周之后就能跟着两个师兄做android开发,师兄都是大神,身为小白的我只能多多学习,多多努力。最近一段时间都忙的没机会总结,今天刚完成了android客户端图片异步加载的类,这里记录一下(ps:其实我这里都是参考网上开源实现)


原理
在ListView或者GridView中加载图片的原理基本都是一样的:

    先从内存缓存中获取,取到则返回,取不到进行下一步
    从文件缓存中获取,取到则返回并更新到内存缓存,取不到则进行进行下一步
    从网络上下载图片,并更新内存缓存和文件缓存


流程图如下:

同时,要注意线程的数量。一般在listview中加载图片,大家都是开启新的线程去加载,但是当快速滑动时,很容易造成OOM,因此需要控制线程数量。我们可以通过线程池控制线程的数量,具体线程池的大小还需要根据处理器的情况和业务情况自行判断

建立线程池的方法如下:

   

ExecutorService executorService = Executors.newFixedThreadPool(5); // 5是可变的 

文件缓存类

   

 import java.io.File; 
   
  import android.content.Context; 
   
  public class FileCache { 
    private static final String DIR_NAME = "your_dir"; 
    private File cacheDir; 
   
    public FileCache(Context context) { 
      // Find the directory to save cached images 
      if (android.os.Environment.getExternalStorageState().equals( 
          android.os.Environment.MEDIA_MOUNTED)) { 
        cacheDir = new File( 
            android.os.Environment.getExternalStorageDirectory(), 
            DIR_NAME); 
      } else { 
        cacheDir = context.getCacheDir(); 
      } 
   
      if (!cacheDir.exists()) { 
        cacheDir.mkdirs(); 
      } 
    } 
   
    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() { 
      File[] files = cacheDir.listFiles(); 
      if (files == null) { 
        return; 
      } else { 
        for (File f : files) { 
          f.delete(); 
        } 
      } 
    } 
  } 

内存缓存类
这里使用了软引用,Map<String, SoftReference<Bitmap>> cache,可以google一下软引用的机制,简单的说:实现了map,同时当内存紧张时可以被回收,不会造成内存泄露

   

 import java.lang.ref.SoftReference; 
  import java.util.Collections; 
  import java.util.LinkedHashMap; 
  import java.util.Map; 
   
  import android.graphics.Bitmap; 
   
  public class MemoryCache { 
    private Map<String, SoftReference<Bitmap>> cache = Collections 
        .synchronizedMap(new LinkedHashMap<String, SoftReference<Bitmap>>( 
            10, 1.5f, true)); 
   
    public Bitmap get(String id) { 
      if (!cache.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<Bitmap>(bitmap)); 
    } 
   
    public void clear() { 
      cache.clear(); 
    } 
  } 

图片加载类

  import java.io.File; 
  import java.io.FileInputStream; 
  import java.io.FileNotFoundException; 
  import java.io.FileOutputStream; 
  import java.io.InputStream; 
  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 java.util.concurrent.ExecutorService; 
  import java.util.concurrent.Executors; 
   
  import android.content.Context; 
  import android.graphics.Bitmap; 
  import android.graphics.BitmapFactory; 
  import android.os.Handler; 
  import android.widget.ImageView; 
   
  public class ImageLoader { 
    /** 
     * Network time out 
     */ 
    private static final int TIME_OUT = 30000; 
    /** 
     * Default picture resource 
     */ 
    private static final int DEFAULT_BG = R.drawable.plate_list_head_bg; 
   
    /** 
     * Thread pool number 
     */ 
    private static 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> imageViews = Collections 
        .synchronizedMap(new WeakHashMap<ImageView, String>()); 
   
    /** 
     * Thread pool 
     */ 
    ExecutorService executorService; 
   
    /** 
     * Handler to display images in UI thread 
     */ 
    Handler handler = new Handler(); 
   
    public ImageLoader(Context context) { 
      fileCache = new FileCache(context); 
      executorService = Executors.newFixedThreadPool(THREAD_NUM); 
    } 
   
    public void disPlayImage(String url, ImageView imageView) { 
      imageViews.put(imageView, url); 
      Bitmap bitmap = memoryCache.get(url); 
      if (bitmap != null) { 
        // Display image from Memory cache 
        imageView.setImageBitmap(bitmap); 
      } else { 
        // Display image from File cache or Network 
        queuePhoto(url, imageView); 
      } 
    } 
   
    private void queuePhoto(String url, ImageView imageView) { 
      PhotoToLoad photoToLoad = new PhotoToLoad(url, imageView); 
      executorService.submit(new PhotosLoader(photoToLoad)); 
    } 
   
    private Bitmap getBitmap(String url) { 
      File f = fileCache.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); 
        HttpURLConnection conn = (HttpURLConnection) imageUrl 
            .openConnection(); 
        conn.setConnectTimeout(TIME_OUT); 
        conn.setReadTimeout(TIME_OUT); 
        conn.setInstanceFollowRedirects(true); 
        InputStream is = conn.getInputStream(); 
        OutputStream os = new FileOutputStream(f); 
        copyStream(is, os); 
        os.close(); 
        conn.disconnect(); 
        bitmap = decodeFile(f); 
        return bitmap; 
      } catch (Throwable ex) { 
        if (ex instanceof OutOfMemoryError) { 
          clearCache(); 
        } 
        return null; 
      } 
   
    } 
   
    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.write(bytes, 0, count); 
        } 
   
      } catch (Exception e) { 
   
      } 
    } 
   
    private Bitmap decodeFile(File f) { 
      try { 
        // TODO:Compress image size 
        FileInputStream fileInputStream = new FileInputStream(f); 
        Bitmap bitmap = BitmapFactory.decodeStream(fileInputStream); 
        return bitmap; 
   
      } catch (FileNotFoundException e) { 
        return null; 
      } 
    } 
   
    private void clearCache() { 
      memoryCache.clear(); 
      fileCache.clear(); 
    } 
   
    /** 
     * Task for the queue 
     * 
     * @author zhengyi.wzy 
     * 
     */ 
    private class PhotoToLoad { 
      public String url; 
      public ImageView imageView; 
   
      public PhotoToLoad(String url, ImageView imageView) { 
        this.url = url; 
        this.imageView = imageView; 
      } 
    } 
   
    /** 
     * Asynchronous to load picture 
     * 
     * @author zhengyi.wzy 
     * 
     */ 
    class PhotosLoader implements Runnable { 
      PhotoToLoad photoToLoad; 
   
      public PhotosLoader(PhotoToLoad photoToLoad) { 
        this.photoToLoad = photoToLoad; 
      } 
   
      private boolean imageViewReused(PhotoToLoad photoToLoad) { 
        String tag = imageViews.get(photoToLoad.imageView); 
        if (tag == null || !tag.equals(photoToLoad.url)) { 
          return true; 
        } 
   
        return false; 
      } 
   
      @Override 
      public void run() { 
        // Abort current thread if Image View reused 
        if (imageViewReused(photoToLoad)) { 
          return; 
        } 
   
        Bitmap bitmap = getBitmap(photoToLoad.url); 
   
        // Update Memory 
        memoryCache.put(photoToLoad.url, bitmap); 
   
        if (imageViewReused(photoToLoad)) { 
          return; 
        } 
   
        // Don't change UI in children thread 
        BitmapDisplayer bd = new BitmapDisplayer(bitmap, photoToLoad); 
        handler.post(bd); 
      } 
   
      class BitmapDisplayer implements Runnable { 
        Bitmap bitmap; 
        PhotoToLoad photoToLoad; 
   
        public BitmapDisplayer(Bitmap bitmap, PhotoToLoad photoToLoad) { 
          this.bitmap = bitmap; 
          this.photoToLoad = photoToLoad; 
        } 
   
        @Override 
        public void run() { 
          if (imageViewReused(photoToLoad)) { 
            return; 
          } 
   
          if (bitmap != null) { 
            photoToLoad.imageView.setImageBitmap(bitmap); 
          } else { 
            photoToLoad.imageView.setImageResource(DEFAULT_BG); 
          } 
        } 
   
      } 
    } 
  } 

调用方法

  ImageLoader imageLoader = new ImageLoader(context); 
  imageLoader.disPlayImage(imageUrl, imageView); 


 类似资料:
  • 本文向大家介绍Android实现异步加载图片,包括了Android实现异步加载图片的使用技巧和注意事项,需要的朋友参考一下 麦洛开通博客以来,有一段时间没有更新博文了.主要是麦洛这段时间因项目开发实在太忙了.今天周六还在公司加班,苦逼程序猿都是这样生活的. 今天在做项目的时候,有一个实现异步加载图片的功能,虽然比较简单但还是记录一下吧.因为麦洛之前实现异步加载图片都是使用了AsynTask这个AP

  • 本文向大家介绍Android App中实现图片异步加载的实例分享,包括了Android App中实现图片异步加载的实例分享的使用技巧和注意事项,需要的朋友参考一下 一、概述 一般大量图片的加载,比如GridView实现手机的相册功能,一般会用到LruCache,线程池,任务队列等;那么异步消息处理可以用哪呢? 1、用于UI线程当Bitmap加载完成后更新ImageView 2、在图片加载类初始化时

  • 本文向大家介绍Android实现图片缓存与异步加载,包括了Android实现图片缓存与异步加载的使用技巧和注意事项,需要的朋友参考一下 ImageManager2这个类具有异步从网络下载图片,从sd读取本地图片,内存缓存,硬盘缓存,图片使用动画渐现等功能,已经将其应用在包含大量图片的应用中一年多,没有出现oom。 Android程序常常会内存溢出,网上也有很多解决方案,如软引用,手动调用recyc

  • 本文向大家介绍Android 中使用 AsyncTask 异步读取网络图片,包括了Android 中使用 AsyncTask 异步读取网络图片的使用技巧和注意事项,需要的朋友参考一下  1.新建Android工程AsyncLoadPicture 新建布局文件activity_main.xml主界面为一个GridView,还有其子项布局文件gridview_item.xml 2.功能主界面MainA

  • 本文向大家介绍Android ListView异步加载图片方法详解,包括了Android ListView异步加载图片方法详解的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Android ListView异步加载图片方法。分享给大家供大家参考,具体如下: 先说说这篇文章的优点把,开启线程异步加载图片,然后刷新UI显示图片,而且通过弱引用缓存网络加载的图片,节省了再次连接网络的开销。 这样

  • 本文向大家介绍Android实现图片异步加载及本地缓存,包括了Android实现图片异步加载及本地缓存的使用技巧和注意事项,需要的朋友参考一下 在android项目中访问网络图片是非常普遍性的事情,如果我们每次请求都要访问网络来获取图片,会非常耗费流量,而且图片占用内存空间也比较大,图片过多且不释放的话很容易造成内存溢出。针对上面遇到的两个问题,首先耗费流量我们可以将图片第一次加载上面缓存到本地,