Android下访问网络获取内容时,由于移动网络的稳定性等原因(貌似更厉害的是运营商的流量费用),我们的应用希望能够将访问的内容(主要是图片)缓存到本地,以后访问时直接访问本地图片,达到优化访问速度等目的。
通常的做法是使用一个SoftReference的HashMap来保存remote link url和本地drawable的对应关系,需要访问文件时通过查询hashmap来确定需不需要重新下载。
我们这里将同样使用hashmap,并且将link与本地filename关联,达到缓存的目的:
文件下载使用的类
public class Downloader {
private static final int BUF_SIZE = 4096;
private static String downloadPath = Environment
.getExternalStorageDirectory().toString()
+ File.separator
+ "cache";
/**
* 设置下载路径,如/sdcard/cache的形式,不带反斜线;
* @param downloadPath
*/
public static void setDownloadPath(String downloadPath) {
Downloader.downloadPath = downloadPath;
}
/**
* 通过下载地址得到文件名
* @param downloadUrl
* @return
*/
private static String getShortFileName(String downloadUrl) {
int lastSlashIndex = downloadUrl.lastIndexOf(File.separator);
if (-1 == lastSlashIndex)
return "";
return downloadUrl.substring(lastSlashIndex + 1);
}
/**
* 通过下载地址和本地下载目录得到文件名的绝对路径
* @param downloadUrl
* @return
*/
public static String getFullFileName(String downloadUrl) {
String shortFileName = getShortFileName(downloadUrl);
if ("".equals(shortFileName))
return "";
return downloadPath + File.separator + shortFileName;
}
/**
* 下载指定url文件
*
* @param downloadUrl
* @return
* @throws IOException
*/
public static String downloadFile(String downloadUrl) throws IOException {
String fullFileName = getFullFileName(downloadUrl);
if ("".equals(fullFileName))
throw new IOException("下载地址错误");
// 如果目录不存在,创建目录
File folder = new File(downloadPath);
if ((!folder.exists()) || (!folder.isDirectory()))
if (!folder.mkdirs())
throw new IOException("目录创建失败!");
// 如果文件存在,直接返回文件名;不存在的话创建文件
File file = new File(fullFileName);
if (file.exists())
return fullFileName;
if (!file.exists())
if (!file.createNewFile())
throw new IOException("文件创建失败!");
// 下载内容写入输入流
URL url = new URL(downloadUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
InputStream ins = null;
int respCode = conn.getResponseCode();
if (respCode == 200) {
ins = conn.getInputStream();
} else {
throw new IOException("获取内容错误,错误代码:" + respCode);
}
if (null == ins)
throw new IOException("下载流为空!");
// 将输入流转换写入文件
FileOutputStream outs = new FileOutputStream(file);
int readsize = 0;
byte[] buffer = new byte[BUF_SIZE];
while ((readsize = ins.read(buffer)) != -1) {
outs.write(buffer, 0, readsize);
}
outs.close();
ins.close();
conn.disconnect();
return fullFileName;
}
}
缓存工具类:
public class CacheImageUtils {
private static HashMap<String, String> filemap = new HashMap<String, String>();
private boolean isFileNameValid(String fullFileName) {
if ((null == fullFileName) || ("".equals(fullFileName)))
return false;
else
return true;
}
public void setImageDownloadable(final String downloadUrl, final ImageView v) {
String fullFileName = null;
// 如果已经有链接地址/文件记录,直接取得文件名;否则获取文件名
if (filemap.containsKey(downloadUrl)) {
fullFileName = filemap.get(downloadUrl);
} else {
fullFileName = Downloader.getFullFileName(downloadUrl);
}
// 如果文件名不合法,直接退出
if (!isFileNameValid(fullFileName))
return;
// 文件有效,直接显示
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
String fullFileName = (String) msg.obj;
Drawable drawable = Drawable.createFromPath(fullFileName);
v.setImageDrawable(drawable);
}
};
Thread downloadThread = new Thread() {
@Override
public void run() {
String fullFileName = Downloader.getFullFileName(downloadUrl);
try {
fullFileName = Downloader.downloadFile(downloadUrl);
if (isFileNameValid(fullFileName))
filemap.put(downloadUrl, fullFileName);
Message msg = handler.obtainMessage(0, fullFileName);
handler.sendMessage(msg);
} catch (IOException e) {
e.printStackTrace();
// 发生异常的时候删除文件
if (isFileNameValid(fullFileName)) {
File file = new File(fullFileName);
if (file.exists())
file.delete();
}
// 发生异常的时候删除对应关系
if (filemap.containsKey(downloadUrl))
filemap.remove(downloadUrl);
}
}
};
downloadThread.start();
}
}
测试Activity:
public class CacheImageTestActivity extends Activity {
/** Called when the activity is first created. */
private ImageView img_01;
private ImageView img_02;
private ImageView img_03;
private ImageView img_04;
private Button btn_test;
private CacheImageUtils utils = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ansyimgview);
utils = new CacheImageUtils();
findControls();
initControls();
}
private void initControls() {
btn_test.setOnClickListener(new OnTestClickListener());
}
private void findControls() {
img_01 = (ImageView) findViewById(R.id.aiv_imgview_01);
img_02 = (ImageView) findViewById(R.id.aiv_imgview_02);
img_03 = (ImageView) findViewById(R.id.aiv_imgview_03);
img_04 = (ImageView) findViewById(R.id.aiv_imgview_04);
btn_test = (Button) findViewById(R.id.aiv_btn_test);
}
class OnTestClickListener implements OnClickListener {
@Override
public void onClick(View arg0) {
String downloadUrl_01 = new String(
"http://imgsrc.baidu.com/forum/pic/item/42a98226cffc1e171504db974a90f603728de9d9.jpg");
utils.setImageDownloadable(downloadUrl_01, img_01);
String downloadUrl_02 = new String(
"http://imgsrc.baidu.com/forum/pic/item/4d086e061d950a7bcec82e790ad162d9f3d3c98a.jpg");
utils.setImageDownloadable(downloadUrl_02, img_02);
String downloadUrl_03 = new String(
"http://imgsrc.baidu.com/forum/pic/item/3b87e950352ac65ceebe31d5fbf2b21192138ad9.jpg");
utils.setImageDownloadable(downloadUrl_03, img_03);
String downloadUrl_04 = new String(
"http://imgsrc.baidu.com/forum/pic/item/ca1349540923dd5416c9f0ced109b3de9d8248d9.jpg");
utils.setImageDownloadable(downloadUrl_04, img_04);
}
}
}