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;elsereturn 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() {@Overridepublic void handleMessage(Message msg) {String fullFileName = (String) msg.obj;Drawable drawable = Drawable.createFromPath(fullFileName);v.setImageDrawable(drawable);}};Thread downloadThread = new Thread() {@Overridepublic 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;@Overridepublic 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 {@Overridepublic 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);}}}



更多相关文章

  1. Android动态加载技术 简单易懂的介绍方式
  2. Python+PyQT5的子线程更新UI界面
  3. Android(安卓)多包名打包应用
  4. android 数据库处理及操作
  5. Android(安卓)Studio中新建assets文件的两种方法
  6. Android(安卓)怎样通过蓝牙传输文件
  7. Android多分辨率适配经验总结
  8. 创建一个QT for Android的传感器应用应用程序(摘自笔者2015年将出
  9. Android框架浅析

随机推荐

  1. Android实战——Mp3播放器
  2. Android(安卓)ART Hook 实现 - SandHook
  3. Android(安卓)Intent学习笔记
  4. Android中String资源文件的String.format
  5. Android Handler 消息机制
  6. 【Android 性能优化】应用启动优化 ( 安
  7. 史上最详细的Android系统SystemUI 启动过
  8. Kotlin 概览——如何看待 Google 将 Kotl
  9. [Android] [ Android启动流程 ] [ 下 ] [
  10. android之组件2