先定义A缓存:
01
02
03
04
05
06
07
08
09
10
11
|
private
final
HashMap<String, Bitmap>mHardBitmapCache =
new
LinkedHashMap<String, Bitmap>(HARD_CACHE_CAPACITY/
2
,
0
.75f,
true
) {
@Override
protected
booleanremoveEldestEntry(LinkedHashMap.Entry<String, Bitmap> eldest) {
if
(size() >HARD_CACHE_CAPACITY) {
//当map的size大于30时,把最近不常用的key放到mSoftBitmapCache中,从而保证mHardBitmapCache的效率
mSoftBitmapCache.put(eldest.getKey(), newSoftReference<Bitmap>(eldest.getValue()));
return
true
;
}
else
return
false
;
}
};
|
再定于B缓存:
01
02
03
04
05
|
/**
*当mHardBitmapCache的key大于30的时候,会根据LRU算法把最近没有被使用的key放入到这个缓存中。
*Bitmap使用了SoftReference,当内存空间不足时,此cache中的bitmap会被垃圾回收掉
*/
private
final
staticConcurrentHashMap<String, SoftReference<Bitmap>> mSoftBitmapCache =
new
ConcurrentHashMap<String,SoftReference<Bitmap>>(HARD_CACHE_CAPACITY /
2
);
|
从缓存中获取数据:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
/**
* 从缓存中获取图片
*/
private
Bitmap getBitmapFromCache(Stringurl) {
// 先从mHardBitmapCache缓存中获取
synchronized
(mHardBitmapCache) {
final
Bitmap bitmap =mHardBitmapCache.get(url);
if
(bitmap !=
null
) {
//如果找到的话,把元素移到linkedhashmap的最前面,从而保证在LRU算法中是最后被删除
mHardBitmapCache.remove(url);
mHardBitmapCache.put(url,bitmap);
return
bitmap;
}
}
//如果mHardBitmapCache中找不到,到mSoftBitmapCache中找
SoftReference<Bitmap>bitmapReference = mSoftBitmapCache.get(url);
if
(bitmapReference !=
null
) {
final
Bitmap bitmap =bitmapReference.get();
if
(bitmap !=
null
) {
return
bitmap;
}
else
{
mSoftBitmapCache.remove(url);
}
}
return
null
;
}
|
如果缓存中不存在,那么就只能去服务器端去下载:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
/**
* 异步下载图片
*/
class
ImageDownloaderTask extendsAsyncTask<String, Void, Bitmap> {
private
static
final
int
IO_BUFFER_SIZE=
4
*
1024
;
private
String url;
private
finalWeakReference<ImageView> imageViewReference;
public
ImageDownloaderTask(ImageViewimageView) {
imageViewReference = newWeakReference<ImageView>(imageView);
}
@Override
protected
BitmapdoInBackground(String... params) {
final
AndroidHttpClient client =AndroidHttpClient.newInstance(
"Android"
);
url = params[
0
];
final
HttpGet getRequest = newHttpGet(url);
try
{
HttpResponse response =client.execute(getRequest);
final
int
statusCode =response.getStatusLine().getStatusCode();
if
(statusCode !=HttpStatus.SC_OK) {
Log.w(TAG,
"从"
+url +
"中下载图片时出错!,错误码:"
+ statusCode);
return
null
;
}
final
HttpEntity entity =response.getEntity();
if
(entity !=
null
) {
InputStream inputStream =
null
;
OutputStream outputStream =
null
;
try
{
inputStream =entity.getContent();
finalByteArrayOutputStream dataStream =
new
ByteArrayOutputStream();
outputStream = newBufferedOutputStream(dataStream, IO_BUFFER_SIZE);
copy(inputStream,outputStream);
outputStream.flush();
final
byte
[] data =dataStream.toByteArray();
final
Bitmap bitmap =BitmapFactory.decodeByteArray(data,
0
, data.length);
return
bitmap;
}
finally
{
if
(inputStream !=
null
) {
inputStream.close();
}
if
(outputStream !=
null
) {
outputStream.close();
}
entity.consumeContent();
}
}
}
catch
(IOException e) {
getRequest.abort();
Log.w(TAG,
"I/O errorwhile retrieving bitmap from "
+ url, e);
}
catch
(IllegalStateException e) {
getRequest.abort();
Log.w(TAG,
"Incorrect URL:"
+ url);
}
catch
(Exception e) {
getRequest.abort();
Log.w(TAG,
"Error whileretrieving bitmap from "
+ url, e);
}
finally
{
if
(client !=
null
) {
client.close();
}
}
return
null
;
}
|
这是两种做法,还有一些应用在下载的时候使用了线程池和消息队列MQ,对于图片下载的效率要更好一些。有兴趣的同学可以看下。
总结
对于远程图片等相对比较大的资源一定要在异步线程中去获取本地做缓存。