Android下实现图片缓存的实例

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

		}

	}
}



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值