【构建Android缓存模块】(三)Controller & 异步图片加载
来源:互联网 发布:述职报告 知乎 编辑:程序博客网 时间:2024/05/23 16:48
http://my.oschina.net/ryanhoo/blog/93432
上节课我们学习了缓存模块的实现, 缓存分做两份:Memory Cache和File Cache。方法也很简单,分别是:
- 存储文件
- 按唯一key值索引文件
- 清空缓存
区别在于内存缓存读取优先,因为它读写的速度更快。但是考虑到内存限制,退而选用文件存储,分担内存缓存的压力。
原理非常简单,在第一课中已经详细分析了。那么要怎么才能将这个缓存模块与UI模块的显示关联起来呢?在这里我们需要一个控制器,掌管数据流向和读写,同时控制UI的显示。
那么这个控制器需要以下的元素:
- 内存缓存
- 硬盘缓存
- 异步任务处理
- 控制UI显示
1
//caches
2
private
MemoryCache memoryCache;
3
private
FileCache fileCache;
4
//Asynchronous task
5
private
static
AsyncImageLoader imageLoader;
01
class
AsyncImageDownloader
extends
AsyncTask<Void, Void, Bitmap>{
02
private
ImageView imageView;
03
private
String fileName;
04
05
public
AsyncImageDownloader(ImageView imageView, String fileName){
06
this
.imageView = imageView;
07
this
.fileName = fileName;
08
}
09
10
@Override
11
protected
void
onPreExecute() {
12
super
.onPreExecute();
13
imageView.setImageResource(R.drawable.placeholder);
14
}
15
16
@Override
17
protected
Bitmap doInBackground(Void... arg0) {
18
String url = Utils.getRealUrlOfPicture(fileName);
19
HttpResponse response =
new
HttpRetriever().requestGet(url,
null
);
20
Log.i(TAG,
"url: "
+ url);
21
Log.i(TAG,
"respone: "
+ response);
22
InputStream in =
null
;
23
try
{
24
if
(response !=
null
&& response.getEntity() !=
null
)
25
in = response.getEntity().getContent();
26
}
catch
(IllegalStateException e) {
27
e.printStackTrace();
28
return
null
;
29
}
catch
(IOException e) {
30
e.printStackTrace();
31
return
null
;
32
}
33
34
//TODO to be optimized: adjust the size of bitmap
35
return
BitmapFactory.decodeStream(in);
36
}
37
38
@Override
39
protected
void
onPostExecute(Bitmap result) {
40
super
.onPostExecute(result);
41
if
(result !=
null
&& imageView !=
null
)
42
imageView.setImageBitmap(result);
43
44
//TODO cache the bitmap both in sdcard & memory
45
memoryCache.put(fileName, result);
// key is a unique token, value is the bitmap
46
47
fileCache.put(fileName, result);
48
}
49
}
可以看到这个类的构造函数需要两个参数,分别是文件名和对应要显示的ImageView,那么在任务开始的时候,可以为该ImageView设置未下载状态的图片,然后下载完成后更新UI。
注:需要提醒的是,这里的唯一key值,我使用的是文件名,因为我接收到的文件名是唯一的。猿媛们也可以根据自己的需求,设计自己的唯一key值算法。
接下来,我们需要读用key值索引相应的Bitmap:
01
public
Bitmap getBitmap(String key){
02
Bitmap bitmap =
null
;
03
//1. search memory
04
bitmap = memoryCache.get(key);
05
06
//2. search sdcard
07
if
(bitmap ==
null
){
08
File file = fileCache.getFile(key);
09
if
(file !=
null
)
10
bitmap = BitmapHelper.decodeFile(file,
null
);
11
}
12
13
return
bitmap;
14
}
读取到Bitmap后进行显示:
01
public
void
displayBitmap(ImageView imageView, String fileName){
02
//no pic for this item
03
if
(fileName ==
null
||
""
.equals(fileName))
04
return
;
05
06
Bitmap bitmap = getBitmap(fileName);
07
//search in cache, if there is no such bitmap, launch downloads
08
if
(bitmap !=
null
){
09
imageView.setImageBitmap(bitmap);
10
}
11
else
{
12
Log.w(TAG,
"Can't find the file you required."
);
13
new
AsyncImageDownloader(imageView, fileName).execute();
14
}
15
}
不过,我将它应用在一个小项目中,性能还不错。对于小项目的需求,应该是够的。
最后,附上使用方法,以及整个类的源码。
使用方法:
1
AsyncImageLoader imageLoader = AsyncImageLoader.getInstance(
this
);、
2
imageLoader.displayBitmap(imageView, fileName);
源码:
001
<strong>
public
class
AsyncImageLoader {
002
003
private
static
final
String TAG =
"AsyncImageLoader"
;
004
005
//caches
006
private
MemoryCache memoryCache;
007
private
FileCache fileCache;
008
//Asynchronous task
009
private
static
AsyncImageLoader imageLoader;
010
011
class
AsyncImageDownloader
extends
AsyncTask<Void, Void, Bitmap>{
012
private
ImageView imageView;
013
private
String fileName;
014
015
public
AsyncImageDownloader(ImageView imageView, String fileName){
016
this
.imageView = imageView;
017
this
.fileName = fileName;
018
}
019
020
@Override
021
protected
void
onPreExecute() {
022
super
.onPreExecute();
023
imageView.setImageResource(R.drawable.placeholder);
024
}
025
026
@Override
027
protected
Bitmap doInBackground(Void... arg0) {
028
String url = Utils.getRealUrlOfPicture(fileName);
029
HttpResponse response =
new
HttpRetriever().requestGet(url,
null
);
030
Log.i(TAG,
"url: "
+ url);
031
Log.i(TAG,
"respone: "
+ response);
032
InputStream in =
null
;
033
try
{
034
if
(response !=
null
&& response.getEntity() !=
null
)
035
in = response.getEntity().getContent();
036
}
catch
(IllegalStateException e) {
037
e.printStackTrace();
038
return
null
;
039
}
catch
(IOException e) {
040
e.printStackTrace();
041
return
null
;
042
}
043
044
//TODO to be optimized: adjust the size of bitmap
045
return
BitmapFactory.decodeStream(in);
046
}
047
048
@Override
049
protected
void
onPostExecute(Bitmap result) {
050
super
.onPostExecute(result);
051
if
(result !=
null
&& imageView !=
null
)
052
imageView.setImageBitmap(result);
053
054
//TODO cache the bitmap both in sdcard & memory
055
memoryCache.put(fileName, result);
// key is a unique token, value is the bitmap
056
057
fileCache.put(fileName, result);
058
}
059
}
060
061
private
AsyncImageLoader(Context context){
062
this
.memoryCache =
new
MemoryCache();
063
this
.fileCache =
new
FileCache(context);
064
}
065
066
public
static
AsyncImageLoader getInstance(Context context){
067
if
(imageLoader ==
null
)
068
imageLoader =
new
AsyncImageLoader(context);
069
070
return
imageLoader;
071
}
072
073
public
void
displayBitmap(ImageView imageView, String fileName){
074
//no pic for this item
075
if
(fileName ==
null
||
""
.equals(fileName))
076
return
;
077
078
Bitmap bitmap = getBitmap(fileName);
079
//search in cache, if there is no such bitmap, launch downloads
080
if
(bitmap !=
null
){
081
imageView.setImageBitmap(bitmap);
082
}
083
else
{
084
Log.w(TAG,
"Can't find the file you required."
);
085
new
AsyncImageDownloader(imageView, fileName).execute();
086
}
087
}
088
089
public
Bitmap getBitmap(String key){
090
Bitmap bitmap =
null
;
091
//1. search memory
092
bitmap = memoryCache.get(key);
093
094
//2. search sdcard
095
if
(bitmap ==
null
){
096
File file = fileCache.getFile(key);
097
if
(file !=
null
)
098
bitmap = BitmapHelper.decodeFile(file,
null
);
099
}
100
101
return
bitmap;
102
}
103
104
public
void
clearCache(){
105
if
(memoryCache !=
null
)
106
memoryCache.clear();
107
if
(fileCache !=
null
)
108
fileCache.clear();
109
}
110
}</strong>
源码:
附上源码,不过服务器的源码暂时还没有放出来,先看看客户端的吧。
https://github.com/ryanhoo/SoftRead
- 【构建Android缓存模块】(三)Controller & 异步图片加载
- 【构建Android缓存模块】(三)Controller & 异步图片加载
- 【构建Android缓存模块】(三)Controller & 异步图片加载
- 【构建Android缓存模块】(三)Controller & 异步图片加载
- 【构建Android缓存模块】(三)Controller & 异步图片加载
- 【构建Android缓存模块】(三)Controller & 异步图片加载
- android异步图片加载中的图片缓存
- android ListView异步加载图片(双缓存)
- android ListView异步加载图片(双缓存)
- android ListView异步加载图片(双缓存)
- android ListView异步加载图片(双缓存)
- android ListView异步加载图片(双缓存)
- Android图片管理组件(双缓存+异步加载)
- Android图片管理组件(双缓存+异步加载)
- Android图片管理组件(双缓存+异步加载)
- Android图片管理组件(双缓存+异步加载)
- Android图片管理组件(双缓存、异步加载)
- android ListView异步加载图片(双缓存)
- int 0x13 的扩展读(ah = 0x42)
- 【构建Android缓存模块】(二)Memory Cache & File Cache
- linux 用户空间通过makefile向程序传递参数
- Device eth0 has different MAC address than expected, ignoring
- WIFI 基本名词诠释
- 【构建Android缓存模块】(三)Controller & 异步图片加载
- jquery有用插件 收集
- Android 缓存Bitmaps
- 复制表结构和内容到另一张表中的SQL
- Linux命令行计算器bc
- 对三层和MVC的认识过程 .
- 09-分位显示(字符串处理)
- 使用 bochs+vmware+windbg 分析调试 windows 7 内核
- 软工课题实验报告五——心得