android读取大图片并缓存

news/2024/7/7 20:05:07
最近开发电视版的云存储应用,要求”我的相册“模块有全屏预览图片的功能,全屏分辨率是1920*1080超清。
UI组件方面采用Gallery+ImageSwitcher组合,这里略过,详情参见google Android API。
相册图片预取缓存策略是内存缓存(硬引用LruCache、软引用SoftReference<Bitmap>)、外部文件缓存(context.getCachedDir()),缓存中取不到的情况下再向服务端请求下载图片。同时缓存三张图片(当前预览的这张,前一张以及后一张)。
1.内存缓存
//需要导入外部jar文件 android-support-v4.jar
 import android.support.v4.util.LruCache;
 //开辟8M硬缓存空间
 private final int hardCachedSize = 8*1024*1024;  
 //hard cache
 private final LruCache<String, Bitmap> sHardBitmapCache = new LruCache<String, Bitmap>(hardCachedSize){
  @Override
  public int sizeOf(String key, Bitmap value){
   return value.getRowBytes() * value.getHeight();
  }
  @Override
  protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue){
   Log.v("tag", "hard cache is full , push to soft cache");
   //硬引用缓存区满,将一个最不经常使用的oldvalue推入到软引用缓存区
   sSoftBitmapCahe.put(key, new SoftReference<Bitmap>(oldValue));
  }
 }
 //软引用
 private static final int SOFT_CACHE_CAPACITY = 40;
 private final static LinkedHashMap<String, SoftReference<Bitmap>> sSoftBitmapCache =
  new  LinkedHashMao<String, SoftReference<Bitmap>>(SOFT_CACHE_CAPACITY, 0.75f, true){
  @Override
  public SoftReference<Bitmap> put(String key, SoftReference<Bitmap> value){
   return super.input(key, value);
  }
  @Override
  protected boolean removeEldestEntry(LinkedHashMap.Entry<Stirng, SoftReference<Bitmap>> eldest){
   if(size() > SOFT_CACHE_CAPACITY){
    Log.v("tag", "Soft Reference limit , purge one");
    return true;
   }
   return false;
  }
 }
 //缓存bitmap
 public boolean putBitmap(String key, Bitmap bitmap){
  if(bitmap != null){
   synchronized(sHardBitmapCache){
    sHardBitmapCache.put(key, bitmap);
   }
   return true;
  }  
  return false;
 }
 //从缓存中获取bitmap
 public Bitmap getBitmap(String key){
  synchronized(sHardBitmapCache){
   final Bitmap bitmap = sHardBitmapCache.get(key);
   if(bitmap != null)
    return bitmap;
  }
  //硬引用缓存区间中读取失败,从软引用缓存区间读取
  synchronized(sSoftBitmapCache){
   SoftReference<Bitmap> bitmapReference = sSoftBtimapCache.get(key);
   if(bitmapReference != null){
    final Bitmap bitmap2 = bitmapReference.get();
    if(bitmap2 != null)
     return bitmap2;
    else{
     Log.v("tag", "soft reference 已经被回收");
     sSoftBitmapCache.remove(key);
    }
   }
  }
  return null;
 }
2.外部文件缓存
private File mCacheDir = context.getCacheDir();
 private static final int MAX_CACHE_SIZE = 20 * 1024 * 1024; //20M
 private final LruCache<String, Long> sFileCache = new LruCache<String, Long>(MAX_CACHE_SIZE){
  @Override
  public int sizeOf(String key, Long value){
   return value.intValue();
  }
  @Override
  protected void entryRemoved(boolean evicted, String key, Long oldValue, Long newValue){
   File file = getFile(key);
   if(file != null)
    file.delete();
  }
 }
 private File getFile(String fileName) throws FileNotFoundException {
  File file = new File(mCacheDir, fileName);
  if(!file.exists() || !file.isFile())
   throw new FileNotFoundException("文件不存在或有同名文件夹");
  return file;
 }
 //缓存bitmap到外部存储
 public boolean putBitmap(String key, Bitmap bitmap){
  File file = getFile(key);
  if(file != null){
   Log.v("tag", "文件已经存在");
   return true;
  }
  FileOutputStream fos = getOutputStream(key);
  boolean saved = bitmap.compress(CompressFormat.JPEG, 100, fos);
  fos.flush();
  fos.close();
  if(saved){
   synchronized(sFileCache){
    sFileCache.put(key, getFile(key).length());
   }
   return true;
  }
  return false;
 }
 //根据key获取OutputStream
 private FileOutputStream getOutputStream(String key){
  if(mCacheDir == null)
   return null;
  FileOutputStream fos = new FileOutputStream(mCacheDir.getAbsolutePath() + File.separator + key);
  return fos;
 }
 //获取bitmap
 private static BitmapFactory.Options sBitmapOptions;
 static {
  sBitmapOptions = new BitmapFactory.Options();
  sBitmapOptions.inPurgeable=true; //bitmap can be purged to disk
 }
 public Bitmap getBitmap(String key){
  File bitmapFile = getFile(key);
  if(bitmapFile != null){
   Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(bitmapFile), null, sBitmapOptions);
   if(bitmap != null){
    //重新将其缓存至硬引用中
    ...
   }
  }
 }
3.从服务端下载图片
private static String generateKey(String fileId, int width, int height) {  
  String ret = fileId + "_" + Integer.toString(width) + "x" + Integer.toString(height);
  return ret;
 }
 String key = generateKey(...)即可生成唯一的key值
下载成功后调用1内存缓存的putBitmap()函数,缓存图片。
在外部文件缓存中也写入一份,调用2的putBitmap()函数.
4.预览图片的流程
1) 如果预览的图片在内存缓存区中,直接调用1的getBitmap()函数,获取bitmap数据(先在硬引用缓存区查找匹配,若硬引用区匹配失败,再去软引用区匹配)
2) 如果从内存缓存区读取失败,再从外部文件缓存中读取,调用2的getBitmap()函数
3) 如果从外部文件缓存中读取失败,则从服务端下载该图片,过程3.
5.生成key值

http://lihuaxi.xjx100.cn/news/249548.html

相关文章

全“芯”关注用户需求 AMD“超轻薄笔记本”杀出重围

现在10.6寸跟11.6寸的笔记本已经占据整个笔记本市场的15%左右&#xff0c;跟过去只有几个点相比&#xff0c;已经有很大的提升了&#xff0c;几乎是百分之百的提升&#xff0c;超轻薄笔记本是大势所趋。这种趋势也带动了两大芯片巨头英特尔和AMD的角逐&#xff0c;英特尔为新一…

工程师进阶之路(四)

转载自 量子恒道官方博客 地址&#xff1a;http://blog.linezing.com 如何和“老板”沟通 我们是一线工程师的时候&#xff0c;和我们的直接技术管理者沟通是非常容易的。我们的技术架构、代码风格、系统扩展性、工程化全局考虑就是我们赢得信任和信赖的名片。但是随着我们的…

量产工具介绍(2)

前面介绍了量产工具概念&#xff0c;U盘构造&#xff0c;量产工具获取途径&#xff0c;以及国内的芯片分类&#xff0c;今天&#xff0c;我们从注意事项及常见问题继续介绍量产相关知识注意事项厂家推出的量产工具也是在不断提高版本的&#xff0c;新版本添加有新主控型号驱动。…

Web自动化测试 六 ----- selector选择

1、一般情况下都是先定位元素在选择 from selenium.webdriver import Chrome from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as ECdriver Chrome()dr…

两个FTP对传文件

2019独角兽企业重金招聘Python工程师标准>>> #!/bin/bash ftp -n<<! open hostname user username password binary cd /FTP_A_Directory lcd /tmp/tmpSave prompt mget * close bye ! ftp -n<<! open hostname user username password binary cd /…

漫谈Httpclient

引用地址&#xff1a; http://hc.apache.org/httpclient-3.x/ End of life The Commons HttpClient project is now end of life, and is no longer being developed. It has been replaced by the Apache HttpComponents project in its HttpClient andHttpCore modules, whic…

安装MariaDB

结果我还是成功安装了MariaDB&#xff0c;其实大部分时候系统的操作不会有什么问题的&#xff0c;只是有时候会遇到一些问题较折腾。 最简单的指南&#xff1a;https://www.linode.com/docs/databases/mariadb/how-to-install-mariadb-on-centos-7 根据stackoverflow网友的说法…

Annotation

在进行类或方法定义的时候&#xff0c;都可以使用一系列的Annotation&#xff08;public interface Annotation&#xff09;进行声明&#xff0c;如果想要获取这些Annotation的信息&#xff0c;可以直接通过反射来完成。在 java.lang.reflect 里面有一个AccessibleObject类&…