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

使用LruCache和DiskLruCache来下载图片的更多相关文章

  1. 安卓开发笔记——关于图片的三级缓存策略(内存LruCache+磁盘DiskLruCache+网络Volley)

    在开发安卓应用中避免不了要使用到网络图片,获取网络图片很简单,但是需要付出一定的代价——流量.对于少数的图片而言问题不大,但如果手机应用中包含大量的图片,这势必会耗费用户的一定流量,如果我们不加以处理 ...

  2. 综合使用LruCache和DiskLruCache 缓存图片

    Activity public class MainActivity extends Activity {     private GridView mPhotoWall;     private P ...

  3. Android Volley框架的使用(四)图片的三级缓存策略(内存LruCache+磁盘DiskLruCache+网络Volley)

    在开发安卓应用中避免不了要使用到网络图片,获取网络图片很简单,但是需要付出一定的代价——流量.对于少数的图片而言问题不大,但如果手机应用中包含大量的图片,这势必会耗费用户的一定流量,如果我们不加以处理 ...

  4. Android照片墙完整版,的完美结合LruCache和DiskLruCache

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/34093441 在上一篇文章其中,我们学习了DiskLruCache的概念和基本使用 ...

  5. 使用lrucache和diskLrucache实现照片墙

    其实,在真正的项目实战当中如果仅仅是使用硬盘缓存的话,程序是有明显短板的.而如果只使用内存缓存的话,程序当然也会有很大的缺陷.因此,一个优秀的程序必然会将内存缓存和硬盘缓存结合到一起使用,那么本篇文章 ...

  6. Android照片墙完整版,完美结合LruCache和DiskLruCache

    转载地址:http://blog.csdn.net/guolin_blog/article/details/34093441#comments 在上一篇文章当中,我们学习了DiskLruCache的概 ...

  7. 网络图片的获取以及二级缓存策略(Volley框架+内存LruCache+磁盘DiskLruCache)

    在开发安卓应用中避免不了要使用到网络图片,获取网络图片很简单,但是需要付出一定的代价——流量.对于少数的图片而言问题不大,但如果手机应用中包含大量的图片,这势必会耗费用户的一定流量,如果我们不加以处理 ...

  8. C++根据图片url下载图片

    需要使用到URLDownloadToFile()函数,该函数在头文件<urlmon.h>中声明. URLDownloadToFile()函数的定义如下: HRESULT URLDownlo ...

  9. .net 已知图片的网络路径,通过浏览器下载图片

    没什么技术含量,主要留给自己查找方便: 如题,知道图片的完整网络路径的情况下,在浏览器中下载图片的实现: 下面这个方法实现的是把图片读取为byte数组: private byte[] GetImage ...

随机推荐

  1. Spring Framework 开发参考手册中文(在线HTML)

    https://blog.csdn.net/zfrong/article/details/3971722

  2. C#获取实例运行时间StopWatch类

    在程序运行时有时需要获取某一步骤的操作时间,C#提供的StopWatch类可以很方便的实现这一目的. StopWatch sw=new StopWatch(); sw.Start(); //Do So ...

  3. java jar打包命令使用

    用法:jar {ctxu}[vfm0Mi] [jar-文件] [manifest-文件] [-C 目录] 文件名 ... 选项: -c 创建新的存档 -t 列出存档内容的列表 -x 展开存档中的命名的 ...

  4. Android群英传-拼图游戏puzzle-代码设计和实现

    上个周末,3个小时总体上读完了<Android群英传>,本周主要在研究代码层次的设计和实现.  编译安装在手机上,玩了几把,结合代码,一周时间才掌握了整体的思路.  大部分时间,其实花在了 ...

  5. C语言编译和链接

    编译链接是使用高级语言编程所必须的操作,一个源程序只有经过编译.链接操作以后才可以变成计算机可以理解并执行的二进制可执行文件. 编译是指根据用户写的源程序代码,经过词法和语法分析,将高级语言编写的代码 ...

  6. LibSVM-windows

    本系列文章由 @YhL_Leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/50112477 官方Web: https ...

  7. 不安装Oracle客户端,用plsql连接远程Oracle数据库(绝对解决你的问题)

    1,首先准备下载两个软件,一个是instantclient.zip,另一个是plsql安装包.但是得确定您的电脑是32位还是64位,我这边提供了32位和64位的供您下载: 百度网盘:https://p ...

  8. 阿里云部署Docker(9)----Dockerfile脚本定制镜像

    本文为原创文章.转载需注明转自:http://blog.csdn.net/minimicall? viewmode=contents 技术爱好者都是比較懒的.而docker又是开发人员支持起来的.所以 ...

  9. HDU 2196 Computer(求树上每一个节点到其他点的最远距离)

    解题思路: 求出树的直径的两个端点.则树上每一个节点到其它点的最远距离一定是到这两个端点的距离中最长的那一个. #include <iostream> #include <cstri ...

  10. sage开发url替换字符串

    /// <summary>         /// Url字段值替换,无该字段则加入         /// </summary>         /// <param ...