Android 图片二级缓存

具体做法:先从缓存取图片,如果不存在,则从磁盘去取,如果磁盘不存在,则从网上下载,下载下来,先保存到缓存,再保存到磁盘 

第一步:先处理大的位图

/**
 *  采样后的Bitmap
 *  @param options
 *  @param reqWidth
 *  @param reqHeight
 *  return
 * /
public Bitmap decoSampleFromResource(Resources res, int resid, int reqWidth, int reqHeight){
    BitmapFactory.Options options=new BitmapFactory.Options();
​​​​//返回Bitmap的尺寸,不加载到内存
    options.inJustDecodeBounds=true;
    BitmapFactory.decodeResource(res,resid);
    options.inSampleSize=calculateInSamoleSize(options,reqWidth,reqHeight);
​​​​​//加载到内存
    options.inJustDecodeBounds=false;
    return BitmapFactory.decodeResource(res,resid);

}
/**
 *  计算位图的采样比例
 *  @param options
 *  @param reqWidth
 *  @param reqHeight
 *  return
 * /
public static int calculateInSamoleSize(BitmapFactory.Options options,int reqWidth,int reqHeight){
    final  int height=options.outHeight;
    final  int width=options.outWidth;
    int inSampleSize=1;
    if(height>reqHeight || width>reqWidth){
        if(width>height){
            inSampleSize=Math.round((float)height/(float)reqHeight);
        }else{
            inSampleSize=Math.round((float)width/(float)reqWidth);
        }
    }
    return inSampleSize;
}

第二步:在内存中缓存Bitmap

             使用LruCacheh方式做缓存:LruCacheh使用最近最少使用算法,通过LinkedHashMap实现

 private LruCache<String,Bitmap> mMemoryCache;
@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    ProjectApplication.activitys.add(this);
    setContentView(R.layout.activity_brand_info);
​​​​​​//得到当前Activity的内存
    final int memClass=((ActivityManager)this.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();
     //使用当前Activity内存的8分之一做缓存大小
    final int cacheSize=1024*1024*memClass/8;
    mMemoryCache=new LruCache(cacheSize);
}
/**
 *  添加Bitmap内存
 *  @param key
 *  @param Bitmap
 * /
private void addBitmapToMemoryCache(String key,Bitmap bitmap){
if(getBitmapformCache(key)==null){
mMemoryCache.put(key,bitmap);
}
}
/**
 *  从缓存中取Bitmap
 *  @param key
 *  return
 * /
private Bitmap getBitmapformCache(String key){
return mMemoryCache.get(key);
}

第三步:磁盘缓存

           在Github上下载磁盘缓存类DiskLruCache https://github.com/JakeWharton/DiskLruCache

           1.DiskLruCache常用方法:

          

**
 *     打开缓存目录,如果没有创建它
 *     @param directory 缓存目录
 *     @param appVersion app版本号,版本号改变,缓存数据会被清除
 *     @param valueCount 一个key可以对应多少文件,一般一对一
 *      @param maxSize 最大缓存数据量
 *      return
 * /
public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize)
throws IOException {
if (maxSize <= 0) {
throw new IllegalArgumentException("maxSize <= 0");
}
if (valueCount <= 0) {
throw new IllegalArgumentException("valueCount <= 0");
}

// If a bkp file exists, use it instead.
File backupFile = new File(directory, JOURNAL_FILE_BACKUP);
if (backupFile.exists()) {
File journalFile = new File(directory, JOURNAL_FILE);
// If journal file also exists just delete backup file.
if (journalFile.exists()) {
backupFile.delete();
} else {
renameTo(backupFile, journalFile, false);
}
}
/**
 *     通过key可以获得一个DiskLruCache.Editor,通过Editor可以得到一个输出流,然后缓存到本地存储上
 *     @param key 键
 *      return
 * /
public Editor edit(String key) throws IOException {
return edit(key, ANY_SEQUENCE_NUMBER);
}

/**
 *     强制缓存文件到本地
 * /
@Override
public void flush() {
try {
out.flush();
} catch (IOException e) {
hasErrors = true;
}
}
/**
 *     通过可以得到一个Snapshot,如果存在,移动到头部,得到一个输入流InputStream
 *      @param key 键
 *      return
 * /
public synchronized Snapshot get(String key) throws IOException {
checkNotClosed();
validateKey(key);
Entry entry = lruEntries.get(key);
if (entry == null) {
return null;
}

if (!entry.readable) {
return null;
}
/**
 *     缓存目录
 * /
public File getDirectory() {
    return directory;
}

2.使用DiskLruCache:

2.1 权限

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

2.2 判断外部存储是否存在

/**
 *     外部是否存在或者是否被没被移除,那么存在外部存储,反之存在手机系统内存
 *      @param context 上下文
 *       @param uniqueName 唯一的名称
 *      return
 * /
public static File getDiskCacheDir(Context context, String uniqueName) {
final String cachePath = Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) ||!isExternalStorageRemovable() 
? context.getExternalCacheDir().getPath()
: context.getCacheDir().getPath();
return new File(cachePath + File.separator + uniqueName);
}

2.3下载图片

/**
 *     判断根据图片地址下载保存到OutputStream是否成功
 *      @param urlString 在线图片地址
 *      @param OutputStream 输出流
 *      return
 * /
public static File getDiskCacheDir(Context context, String uniqueName) {
final String cachePath = Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) ||!isExternalStorageRemovable()
? context.getExternalCacheDir().getPath()
: context.getCacheDir().getPath();
return new File(cachePath + File.separator + uniqueName);
}
/**
 *     判断根据图片地址下载保存到OutputStream是否成功
 *      @param urlString 在线图片地址
 *      @param OutputStream 输出流
 *      return
 * /

private boolean downloadUrlToStream(String urlString, OutputStream outputStream) {
HttpURLConnection urlConnection = null;
BufferedOutputStream out = null;
BufferedInputStream in = null;

try {
final URL url = new URL(urlString);
urlConnection = (HttpURLConnection) url.openConnection();
in = new BufferedInputStream(urlConnection.getInputStream(), IO_BUFFER_SIZE);
out = new BufferedOutputStream(outputStream, IO_BUFFER_SIZE);
int b;
while ((b = in.read()) != -1) {
out.write(b);
}
return true;
} catch (Exception e) {
Log.e(TAG, "Error in downloadBitmap - " + e);
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (final IOException e) {
}
}
return false;
}

2.4下载下来,开始缓存

/**
 *     下载了图片,实例化diskLruCache,为缓存准备
 *     
 * /
private static final int MAX_SIZE = 10 * 1024 * 1024;//10MB
private DiskLruCache diskLruCache;
private void initDiskLruCache() {
if (diskLruCache == null || diskLruCache.isClosed()) {
try {
File cacheDir = CacheUtil.getDiskCacheDir(this, "CacheDir");
if (!cacheDir.exists()) {
cacheDir.mkdirs();
}
diskLruCache = DiskLruCache.open(cacheDir, 1, 1, MAX_SIZE);
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
 *     异步下载图片,并开始缓存,能缓存则提交,不能则丢弃
 *
 * /
@Override
protected Boolean doInBackground(Object... params) {
try {
String key = Util.hashKeyForDisk(Util.IMG_URL);
DiskLruCache diskLruCache = (DiskLruCache) params[0];
DiskLruCache.Editor editor = diskLruCache.edit(key);
if (editor != null) {
OutputStream outputStream = editor.newOutputStream(0);
if (downloadUrlToStream(Util.IMG_URL, outputStream)) {
publishProgress("");
editor.commit();
} else {
editor.abort();
}
}
diskLruCache.flush();
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}

猜你喜欢

转载自blog.csdn.net/sunshine_0707/article/details/81740502