在android的ListView或者GridView中加载大量图片是非常痛苦的,特别是从网络或者其他地方异步加载,需要一个下载的过程,不可能每次滑动页面都要去重新下载图片,这时候缓存就显得尤为重要了。
我的需求是:显示所有视频的缩略图,并且显示视频时长。
获取视频缩略图的代码:
public static Bitmap getVideoThumbnail(String filePath) { Bitmap bitmap = null; MediaMetadataRetriever retriever = new MediaMetadataRetriever(); try { retriever.setDataSource(filePath); bitmap = retriever.getFrameAtTime(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (RuntimeException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { try { retriever.release(); } catch (RuntimeException e) { e.printStackTrace(); } } return bitmap; }每次获取视频的缩略图都需要一定的时间,所以我们需要缓存图片,缓存的核心类是LruCache。 public class VideoLoader { private LruCache<String, Bitmap> bitmapCache; // 图片缓存 public VideoLoader() { int maxMemory = (int) Runtime.getRuntime().maxMemory();//获取应用最大的运行内存 int maxSize = maxMemory / 3;//拿到缓存的内存大小,分配1/3 bitmapCache = new LruCache<String, Bitmap>(maxSize) { @Override protected int sizeOf(String key, Bitmap value) { //这个方法会在每次存入缓存的时候调用 return value.getByteCount(); } }; } public void addVideoThumbToCache(String path, Bitmap bitmap) { if (getVideoThumbFromCache(path) == null) { //当前地址没有缓存时,就添加 bitmapCache.put(path, bitmap); } } public Bitmap getVideoThumbFromCache(String path) { return bitmapCache.get(path); } public void showThumbByAsynctack(String path, ImageView imgview) { if (getVideoThumbFromCache(path) == null) { //异步加载 new BitmapAsynctack(imgview, path).execute(path); } else { imgview.setImageBitmap(getVideoThumbFromCache(path)); } } /** * 图片异步加载 */ class BitmapAsynctack extends AsyncTask<String, Void, Bitmap> { private ImageView imgView; private String path; public BitmapAsynctack(ImageView imageView, String path) { this.imgView = imageView; this.path = path; } @Override protected Bitmap doInBackground(String... params) { Bitmap bitmap = BitmapUtil.getVideoThumbnail(params[0]); //加入缓存中 if (getVideoThumbFromCache(params[0]) == null) { addVideoThumbToCache(path, bitmap); } return bitmap; } @Override protected void onPostExecute(Bitmap bitmap) { if (imgView.getTag().equals(path)) {//通过 Tag可以绑定 图片地址和 imageView,这是解决Listview加载图片错位的解决办法之一 imgView.setImageBitmap(bitmap); } } } }分配内存大小是按照需求来定,获取到最大内存maxMemory后,我一开始设置的是maxMemory/4,发现分配的内存太小,缓存根本就不起作用,每次都要重新去获取一次图片,所以后面我增加了缓存内存,分配maxMemory/3。LruCache在不使用的时候会自动释放内存,帮助我们实现内存管理。使用缓存时手机内存占用情况:
可以看到内存一直在上升,在我们使用完后它会自己释放内存:
使用代码:
// 设置tag holder.pictureImageView.setTag(data.get(position)); holder.pictureImageView.setScaleType(ImageView.ScaleType.CENTER_CROP); mVideoLoader.showThumbByAsynctack(data.get(position), holder.pictureImageView, holder.durationTextView);效果图:
参考:
http://www.mobile-open.com/2015/41278.html
http://blog.csdn.net/i_lovefish/article/details/8220077