LruCache是一个非常好用的图片缓存工具:

主要做法是:滑动图片时将图片的bitmap缓存在LruCache<String, Bitmap>中,退出程序后将图片缓存进文件中。採用DiskLruCache mDiskLruCache

所以我们必须设置一个图片缓存的地址:

public void setImageCache(){
String strPath = null;
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
File sdFile = Environment.getExternalStorageDirectory();
strPath = sdFile.getAbsolutePath() + "/pic/";
File cacheFile = new File(strPath);
if(!cacheFile.exists()){
cacheFile.mkdir();
}
}
else{
String strCacheDir = this.getCacheDir().getAbsolutePath();
strPath = strCacheDir + "/pic/";
}
setCachePath(strPath);
} private void setCachePath(String strPicCachePath){
if(TextUtils.isEmpty(strPicCachePath)){
return;
}
m_strPicCachePath = strPicCachePath;
File cacheFile = new File(strPicCachePath);
if(!cacheFile.exists()){
cacheFile.mkdir();
}
} public String getCacheBmpPath(String strUrl){
if(TextUtils.isEmpty(m_strPicCachePath) || TextUtils.isEmpty(strUrl)){
return "";
}
return m_strPicCachePath + StringUtil.MD5Encode(strUrl) + mFileExName;//".bmp";
}

然后写List的adapter:

	private class ListAdapter extends BaseAdapter implements OnScrollListener {

		protected List<ShopData> items = new ArrayList<ShopData>();
protected static final int FETCH_IMAGE_MSG = 1;
private LruCache<String, Bitmap> mMemoryCache;
protected HashSet<ImageView> mItemsMissingImages = new HashSet<ImageView>();
protected ImageLoaderHandler mHandler;
protected ImageLoader mImageFetcher;
public static final int TIMEOUT = 30000;//超时时间30秒
private DiskLruCache mDiskLruCache; public ListAdapter() {
super();
mHandler = new ImageLoaderHandler();
int maxMemory = (int) Runtime.getRuntime().maxMemory();
int mCacheSize = maxMemory / 8;
// 给LruCache分配1/8 4M
mMemoryCache = new LruCache<String, Bitmap>(mCacheSize) { // 必须重写此方法,来測量Bitmap的大小
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight();
} }; try {
mDiskLruCache = DiskLruCache
.open(new File(m_strPicCachePath), getAppVersion(MainActivityTest.this), 1, 10 * 1024 * 1024);
} catch (IOException e) {
e.printStackTrace();
} } /**
* 将缓存记录同步到journal文件里。 */
public void fluchCache() {
if (mDiskLruCache != null) {
try {
mDiskLruCache.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
} @Override
public int getCount() {
return items.size();
} @Override
public Object getItem(int position) {
return items.get(position);
} @Override
public long getItemId(int position) {
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) { ShopDataTag tag = new ShopDataTag();
if (convertView == null) {
convertView = mInflater.inflate(R.layout.listitem, null);
tag.name = (TextView) convertView.findViewById(R.id.name);
tag.shopInfo = (TextView) convertView.findViewById(R.id.info);
tag.icon = (ImageView) convertView.findViewById(R.id.image_icon);
convertView.setTag(tag);
} else {
tag = (ShopDataTag) convertView.getTag();
} TextView name = tag.name;
TextView info = tag.shopInfo;
ImageView imageView = tag.icon;
ShopData data = items.get(position);
name.setText(data.name);
info.setText(data.info);
imageView.setTag(data.url);
setContactPhoto(data.url, imageView);
return convertView;
} protected void setContactPhoto(String url,ImageView viewToUse) {
if(TextUtils.isEmpty(url)) {
viewToUse.setImageResource(R.drawable.avatar);
}else{
//先看mMemoryCache里能不能得到bitmap
Bitmap bitmap = mMemoryCache.get(url);
if (bitmap != null) {
viewToUse.setImageBitmap(bitmap);
} else {
Snapshot snapShot = null;
FileDescriptor fileDescriptor = null;
FileInputStream fileInputStream = null;
try {
//由于mDiskLruCache会把key作为文件名称。所以把url通过md5转换为key
final String key = hashKeyForDisk(url);
snapShot = mDiskLruCache.get(key);
//假设snapShot为空,就是没找到相应的文件
if (snapShot == null) {
//这里去下载
fetchImage(viewToUse);
}else{
fileInputStream = (FileInputStream) snapShot.getInputStream(0);
fileDescriptor = fileInputStream.getFD();
if (fileDescriptor != null) {
bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);
}
//假设解析文件成bitmap失败。又一次下载
if(!TextUtils.isEmpty(url) && bitmap != null){
mMemoryCache.put(url, bitmap);
viewToUse.setImageBitmap(bitmap);
}else{
fetchImage(viewToUse);
}
}
}catch(IOException ex) {
ex.printStackTrace();
}finally{
if (fileDescriptor == null && fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
}
}
} }
}
} private void fetchImage(ImageView viewToUse) {
viewToUse.setImageResource(R.drawable.avatar);
mItemsMissingImages.add(viewToUse);
if (mScrollState != OnScrollListener.SCROLL_STATE_FLING) {
sendFetchImageMessage(viewToUse);
}
} public String <strong>hashKeyForDisk</strong>(String key) { 将key转换为md5文件
return StringUtil.MD5Encode(key);
} // image downloader
private class ImageLoaderHandler extends Handler {
@Override
public void handleMessage(Message message) {
if (isFinishing()) {
return;
}
switch (message.what) {
case FETCH_IMAGE_MSG: {
final ImageView imageView = (ImageView) message.obj;
if (imageView == null) {
break;
} final String url = (String) imageView.getTag();
if (TextUtils.isEmpty(url)) {
break;
} Bitmap map = getBitmapFromMemCache(url);
if (map == null) {
break;
} synchronized (imageView) {
final String myUrl = (String) imageView.getTag();
if (TextUtils.equals(url, myUrl)) {
imageView.setImageBitmap(map);
mItemsMissingImages.remove(imageView);
} else {
}
}
break;
}
}
} public void clearImageFecthing() {
removeMessages(FETCH_IMAGE_MSG);
}
} private class ImageLoader implements Runnable {
String url;
private ImageView mImageView; public ImageLoader(String url, ImageView imageView) {
this.url = url;
this.mImageView = imageView;
} public void run() {
if (isFinishing()) {
return;
} if (Thread.interrupted()) {
return;
} FileDescriptor fileDescriptor = null;
FileInputStream fileInputStream = null;
Snapshot snapShot = null;
try {
final String key = hashKeyForDisk(url);
snapShot = mDiskLruCache.get(key);
if (snapShot == null) {
// 假设没有找到相应的缓存,则准备从网络上请求数据。并写入缓存
DiskLruCache.Editor editor = mDiskLruCache.edit(key);
if (editor != null) {
OutputStream outputStream = editor.newOutputStream(0);
boolean flag = downloadImage(url, outputStream);
if (flag) {
editor.commit();
} else {
editor.abort();
}
}
// 缓存被写入后,再次查找key相应的缓存
snapShot = mDiskLruCache.get(key);
}
//这里应该删除相应的文件 if (snapShot != null) {
fileInputStream = (FileInputStream) snapShot.getInputStream(0);
fileDescriptor = fileInputStream.getFD();
} // 将缓存数据解析成Bitmap对象
Bitmap bitmap = null;
if (fileDescriptor != null) {
bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);
}
if (bitmap != null) {
// 将Bitmap对象加入到内存缓存其中
mMemoryCache.put(url, bitmap);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileDescriptor == null && fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
}
}
} if (Thread.interrupted()) {
return;
} Message msg = new Message();
msg.what = FETCH_IMAGE_MSG;
msg.obj = mImageView;
mHandler.sendMessage(msg);
}
} public Bitmap getBitmapFromMemCache(String key) {
return mMemoryCache.get(key);
} public boolean downloadImage(String strUrl,OutputStream fos) { URL getUrl = null;
Bitmap bitmap = null;
BufferedOutputStream out = null;
BufferedInputStream in = null;
try {
getUrl = new URL(strUrl);
} catch (MalformedURLException ex) {
Log.e("HttpUtil", "get MalformedURL", ex);
return false;
}
InputStream input = null;
HttpURLConnection conn = null;
try {
conn = (HttpURLConnection)getUrl.openConnection();
conn.setConnectTimeout(TIMEOUT);
conn.setReadTimeout(TIMEOUT);
conn.setDoInput(true);
conn.connect();
input = conn.getInputStream();
in = new BufferedInputStream(input, 8 * 1024);
out = new BufferedOutputStream(fos, 8 * 1024);
int b;
while ((b = in.read()) != -1) {
out.write(b);
}
return true;
} catch (Exception ex) {
Log.e("HttpUtil", "downloadImage", ex);
} catch(OutOfMemoryError ex){
ex.printStackTrace();
} finally {
try {
if(out != null){
out.close();
out = null;
}
if (in != null){
in.close();
in = null;
}
if (conn != null){
conn.disconnect();
conn = null;
}
} catch (Exception ex) {
Log.e("HttpUtil", "downloadImage finally", ex);
}
}
return false;
} private boolean getResponse(InputStream input, OutputStream os, byte[] data) throws IOException{
if(input == null || os == null || data == null){
return false;
}
int i = 0;
while( (i = input.read(data)) != -1){
os.write(data, 0, i);
os.flush();
}
os.flush();
return true;
} private void processMissingImageItems(AbsListView view) {
for (ImageView iv : mItemsMissingImages) {
sendFetchImageMessage(iv);
}
} protected void sendFetchImageMessage(ImageView view) {
final String url = (String) view.getTag();
if (TextUtils.isEmpty(url)) {
return;
}
mImageFetcher = new ImageLoader(url, view);
synchronized (MainActivityTest.this) {
if (sImageFetchThreadPool == null) {
sImageFetchThreadPool = Executors.newFixedThreadPool(3);
}
sImageFetchThreadPool.execute(mImageFetcher);
}
} public void clearImageFetching() {
synchronized (MainActivityTest.this) {
if (sImageFetchThreadPool != null) {
sImageFetchThreadPool.shutdownNow();
sImageFetchThreadPool = null;
}
} mHandler.clearImageFecthing();
} public void clearMessages() {
if (mHandler != null) {
try {
mHandler.removeCallbacksAndMessages(null);
} catch (java.lang.Throwable th) {
}
mHandler = null;
}
} @Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
mScrollState = scrollState;
if (scrollState == OnScrollListener.SCROLL_STATE_FLING) {
clearImageFetching();
} else {
processMissingImageItems(view);
}
} @Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { } } private class ShopDataTag {
TextView name;
TextView shopInfo;
ImageView icon;
}

效果图:

代码:http://download.csdn.net/detail/baidu_nod/7777137

最新文章

  1. 【codeforces 442B】 Andrey and Problem
  2. linux删除文件后沒有释放空间
  3. 【C解毒】怎样写main()函数
  4. 第十章:鸟哥的Linux私房菜
  5. SQL注入测试用例
  6. acdream 1044
  7. BZOJ 1013: [JSOI2008]球形空间产生器sphere 高斯消元
  8. 结构体定义 typedef struct 用法详解和用法小结
  9. 佛祖保佑 永无BUG 永不改动
  10. C语言sqrt函数
  11. 安卓服务Service详解
  12. 【原创】Linux基础之SSH秘钥登录
  13. PDF 补丁丁 0.6.0.3413 版发布(修复提取图片问题,增加自动检查软件更新功能)
  14. 站在DevOps肩膀上的TestOps(二)
  15. wekpack笔记
  16. Java IO流学习总结六:ByteArrayInputStream、ByteArrayOutputStream
  17. 部分开源gis 方案的比较
  18. python2.7中MySQLdb的安装与使用详解
  19. 阿里数据服务P6~P7晋升要点
  20. ROC曲线和PR曲线绘制【转】

热门文章

  1. apicloud 上传/更新App版本到 ios store 流程步骤
  2. luogu P4018 Roy&amp;October之取石子(博弈论)
  3. RHEL8.0-beta-1.ISO
  4. Hibernate中如何完成持久化类和数据库映射文件
  5. Myeclipse学习总结(8)——Eclipse实用操作
  6. CodeForces - 552E Vanya and Brackets
  7. Oracle11g R2创建PASSWORD_VERIFY_FUNCTION相应password复杂度验证函数步骤
  8. POJ 3368 Frequent values(RMQ 求区间出现最多次数的数字的次数)
  9. Python Tkinter 基础控件学习
  10. asp.net的临时文件夹