现在的位置: 首页 > 综合 > 正文

Android异步加载图片并缓存到内存和SD卡上

2013年02月24日 ⁄ 综合 ⁄ 共 3427字 ⁄ 字号 评论关闭
* 异步加载图片
 * 使用方法:
 * private AsyncImageLoader asyImg = new AsyncImageLoader();
 * asyImg.LoadImage(productItems.get(position).getPic(), (ImageView)view.findViewById(R.id.pic));
 */

public class AsyncImageLoader {
	// 为了加快速度,在内存中开启缓存(主要应用于重复图片较多时,或者同一个图片要多次被访问,比如在ListView时来回滚动)
	public Map<String, SoftReference<Drawable>> imageCache = new HashMap<String, SoftReference<Drawable>>();
	private ExecutorService executorService = Executors.newFixedThreadPool(5); // 固定五个线程来执行任务
	private final Handler handler = new Handler();
	// SD卡上图片储存地址
	private final String path = Environment.getExternalStorageDirectory()
			.getPath() + "/maiduo";

	/**
	 * 
	 * @param imageUrl
	 *            图像url地址
	 * @param callback
	 *            回调接口
	 * @return 返回内存中缓存的图像,第一次加载返回null
	 */
	public Drawable loadDrawable(final String imageUrl,
			final ImageCallback callback) {
		// 如果缓存过就从缓存中取出数据
		if (imageCache.containsKey(imageUrl)) {
			SoftReference<Drawable> softReference = imageCache.get(imageUrl);
			if (softReference.get() != null) {
				return softReference.get();
			}
		} else if (useTheImage(imageUrl) != null) {
			return useTheImage(imageUrl);
		}
		// 缓存中没有图像,则从网络上取出数据,并将取出的数据缓存到内存中
		executorService.submit(new Runnable() {
			public void run() {
				try {
					final Drawable drawable = Drawable.createFromStream(
							new URL(imageUrl).openStream(), "image.png");
					imageCache.put(imageUrl, new SoftReference<Drawable>(
							drawable));
					handler.post(new Runnable() {
						public void run() {
							callback.imageLoaded(drawable);
						}
					});
					saveFile(drawable, imageUrl);
				} catch (Exception e) {
					throw new RuntimeException(e);
				}
			}
		});
		return null;
	}

	// 从网络上取数据方法
	public Drawable loadImageFromUrl(String imageUrl) {
		try {

			return Drawable.createFromStream(new URL(imageUrl).openStream(),
					"image.png");
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	// 对外界开放的回调接口
	public interface ImageCallback {
		// 注意 此方法是用来设置目标对象的图像资源
		public void imageLoaded(Drawable imageDrawable);
	}

	// 引入线程池,并引入内存缓存功能,并对外部调用封装了接口,简化调用过程
	public void LoadImage(final String url, final ImageView iv) {
		if (iv.getImageMatrix() == null) {
			iv.setImageResource(R.drawable.loading);
		}
		// 如果缓存过就会从缓存中取出图像,ImageCallback接口中方法也不会被执行
		Drawable cacheImage = loadDrawable(url,
				new AsyncImageLoader.ImageCallback() {
					// 请参见实现:如果第一次加载url时下面方法会执行
					public void imageLoaded(Drawable imageDrawable) {
						iv.setImageDrawable(imageDrawable);
					}
				});
		if (cacheImage != null) {
			iv.setImageDrawable(cacheImage);
		}
	}

	/**
	 * 保存图片到SD卡上
	 * 
	 * @param bm
	 * @param fileName
	 * 
	 */
	public void saveFile(Drawable dw, String url) {
		try {
			BitmapDrawable bd = (BitmapDrawable) dw;
			Bitmap bm = bd.getBitmap();

			// 获得文件名字
			final String fileNa = url.substring(url.lastIndexOf("/") + 1,
					url.length()).toLowerCase();
			File file = new File(path + "/image/" + fileNa);
			// 创建图片缓存文件夹
			boolean sdCardExist = Environment.getExternalStorageState().equals(
					android.os.Environment.MEDIA_MOUNTED); // 判断sd卡是否存在
			if (sdCardExist) {
				File maiduo = new File(path);
				File ad = new File(path + "/image");
				// 如果文件夹不存在
				if (!maiduo.exists()) {
					// 按照指定的路径创建文件夹
					maiduo.mkdir();
					// 如果文件夹不存在
				} else if (!ad.exists()) {
					// 按照指定的路径创建文件夹
					ad.mkdir();
				}
				// 检查图片是否存在
				if (!file.exists()) {
					file.createNewFile();
				}
			}

			BufferedOutputStream bos = new BufferedOutputStream(
					new FileOutputStream(file));
			bm.compress(Bitmap.CompressFormat.JPEG, 100, bos);
			bos.flush();
			bos.close();
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	/**
	 * 使用SD卡上的图片
	 * 
	 */
	public Drawable useTheImage(String imageUrl) {

		Bitmap bmpDefaultPic = null;

		// 获得文件路径
		String imageSDCardPath = path
				+ "/image/"
				+ imageUrl.substring(imageUrl.lastIndexOf("/") + 1,
						imageUrl.length()).toLowerCase();
		File file = new File(imageSDCardPath);
		// 检查图片是否存在
		if (!file.exists()) {
			return null;
		}
		bmpDefaultPic = BitmapFactory.decodeFile(imageSDCardPath, null);

		if (bmpDefaultPic != null || bmpDefaultPic.toString().length() > 3) {
			Drawable drawable = new BitmapDrawable(bmpDefaultPic);
			return drawable;
		} else
			return null;
	}

}
【上篇】
【下篇】

抱歉!评论已关闭.