缓存图片并显示的ImageView

这部分代码通过在sd卡中保存图片文件实现文件方式的缓存,并且在加载时将图片load到内存中,显示时直接使用内存中已有内容。具体代码如下:


package com.example.xxx;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.ImageView;

import com.example.xxx.conf.Configuration;

@SuppressLint("HandlerLeak")
public class ImageLoader {
	// 链接地址字符串
	private String urlString = null;
	// 需要绘制的ImageView
	private ImageView imageView = null;
	// 保存urlString对应的Bitmap
	private Map<String, Bitmap> imageMap = new HashMap<String, Bitmap>();

	private final static int UPDATE_IMAGEVIEW = 1;
	private WorkingThread workingThread = null;
	// 处理刷新主界面的handler
	private Handler handler = new Handler(){
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case UPDATE_IMAGEVIEW:
				displayImage();
				break;
			default:
				super.handleMessage(msg);
				break;
			}
		}
	};

	/**
	 * 后台线程,用于下载网络图片
	 * @author sam
	 * 
	 */
	class WorkingThread extends Thread {
		// 缓冲区大小
		private static final int BUF_SIZE = 4096;
		// 临时文件后缀名
		private final static String SUFFIX = ".tmp";

		@Override
		public void run() {
			try {
				HttpURLConnection conn = (HttpURLConnection) new URL(urlString)
						.openConnection();
				conn.setConnectTimeout(30000);
				conn.setReadTimeout(30000);
				conn.setInstanceFollowRedirects(true);
				InputStream is = conn.getInputStream();
				// 缓存文件名
				String cacheFileName = ImageLoader.getCacheFileName(urlString);
				// 临时文件名
				String tmpFileName = cacheFileName + SUFFIX;
				OutputStream os = new FileOutputStream(tmpFileName);
				byte[] buffer = new byte[BUF_SIZE];
				int size = 0;
				while ((size = is.read(buffer)) > 0) {
					os.write(buffer, 0, size);
				}
				os.close();

				// 写入文件结束,改名
				File tmpFile = new File(tmpFileName);
				if (!tmpFile.renameTo(new File(cacheFileName)))
					Log.e("ImageLoader", "Failed to rename tmpFile.");

				// 通知主线程完成更新
				Message msg = ImageLoader.this.handler.obtainMessage(UPDATE_IMAGEVIEW);
				handler.sendMessage(msg);
			} catch (MalformedURLException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}

			super.run();
		}
	}

	public ImageLoader(String urlString, ImageView imageView) {
		this.urlString = urlString;
		this.imageView = imageView;
	}

	/**
	 * 获得缓存文件名
	 * 
	 * @param urlString
	 * @return
	 */
	public static String getCacheFileName(String urlString) {
		try {
			URL url = new URL(urlString);
			String relativeFilename = url.getFile();
			String[] splitString = relativeFilename.split(File.separator);
			if (splitString.length > 0)
				return Configuration.CACHE_PATH
						+ splitString[splitString.length - 1];
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 在ImageView中显示网络图片
	 * @param urlString
	 * @param imageView
	 */
	public void displayImage() {
		String cacheFileName = getCacheFileName(urlString);
		File cacheFile = new File(cacheFileName);

		// 如果已经缓存过图片,直接显示
		if (imageMap.get(urlString) != null) {
			imageView.setImageBitmap(imageMap.get(urlString));
		} else {
			// 如果文件已经存在,加载到内存中并显示
			if (cacheFile.exists()) {
				Bitmap bm = decodeFile(cacheFile);
				imageMap.put(urlString, bm);
				imageView.setImageBitmap(bm);
			} else {
				// 文件不存在,启动线程后台下载图片
				downloadPicture();
				// 暂时显示默认图片
				imageView.setImageResource(Configuration.DEFAULT_IMAGE);
			}
		}
	}

	/**
	 * 启动线程下载图片
	 */
	private void downloadPicture() {
		workingThread = new WorkingThread();
		workingThread.start();
	}

	/**
	 * 加载图片为Bitmap
	 * @param f
	 * @return
	 */
	private Bitmap decodeFile(File f) {
		try {
			// decode image size
			BitmapFactory.Options o = new BitmapFactory.Options();
			o.inJustDecodeBounds = true;
			BitmapFactory.decodeStream(new FileInputStream(f), null, o);
			// Find the correct scale value. It should be the power of 2.
			final int REQUIRED_SIZE = 70;
			int width_tmp = o.outWidth, height_tmp = o.outHeight;
			int scale = 1;
			while (true) {
				if (width_tmp / 2 < REQUIRED_SIZE
						|| height_tmp / 2 < REQUIRED_SIZE)
					break;

				width_tmp /= 2;
				height_tmp /= 2;
				scale *= 2;
			}

			// decode with inSampleSize
			BitmapFactory.Options o2 = new BitmapFactory.Options();
			o2.inSampleSize = scale;
			return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值