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

人已赞赏
Android文章

android开发之线程池

2021-2-1 8:54:53

Android文章

android开发高德地图自定义图标加图标之间的连线

2021-2-1 9:37:25

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索