使用LruCache和DiskLruCache来下载图片
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;
}
效果图:
使用LruCache和DiskLruCache来下载图片的更多相关文章
- 安卓开发笔记——关于图片的三级缓存策略(内存LruCache+磁盘DiskLruCache+网络Volley)
在开发安卓应用中避免不了要使用到网络图片,获取网络图片很简单,但是需要付出一定的代价——流量.对于少数的图片而言问题不大,但如果手机应用中包含大量的图片,这势必会耗费用户的一定流量,如果我们不加以处理 ...
- 综合使用LruCache和DiskLruCache 缓存图片
Activity public class MainActivity extends Activity { private GridView mPhotoWall; private P ...
- Android Volley框架的使用(四)图片的三级缓存策略(内存LruCache+磁盘DiskLruCache+网络Volley)
在开发安卓应用中避免不了要使用到网络图片,获取网络图片很简单,但是需要付出一定的代价——流量.对于少数的图片而言问题不大,但如果手机应用中包含大量的图片,这势必会耗费用户的一定流量,如果我们不加以处理 ...
- Android照片墙完整版,的完美结合LruCache和DiskLruCache
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/34093441 在上一篇文章其中,我们学习了DiskLruCache的概念和基本使用 ...
- 使用lrucache和diskLrucache实现照片墙
其实,在真正的项目实战当中如果仅仅是使用硬盘缓存的话,程序是有明显短板的.而如果只使用内存缓存的话,程序当然也会有很大的缺陷.因此,一个优秀的程序必然会将内存缓存和硬盘缓存结合到一起使用,那么本篇文章 ...
- Android照片墙完整版,完美结合LruCache和DiskLruCache
转载地址:http://blog.csdn.net/guolin_blog/article/details/34093441#comments 在上一篇文章当中,我们学习了DiskLruCache的概 ...
- 网络图片的获取以及二级缓存策略(Volley框架+内存LruCache+磁盘DiskLruCache)
在开发安卓应用中避免不了要使用到网络图片,获取网络图片很简单,但是需要付出一定的代价——流量.对于少数的图片而言问题不大,但如果手机应用中包含大量的图片,这势必会耗费用户的一定流量,如果我们不加以处理 ...
- C++根据图片url下载图片
需要使用到URLDownloadToFile()函数,该函数在头文件<urlmon.h>中声明. URLDownloadToFile()函数的定义如下: HRESULT URLDownlo ...
- .net 已知图片的网络路径,通过浏览器下载图片
没什么技术含量,主要留给自己查找方便: 如题,知道图片的完整网络路径的情况下,在浏览器中下载图片的实现: 下面这个方法实现的是把图片读取为byte数组: private byte[] GetImage ...
随机推荐
- vue的表格加单选框
https://www.cnblogs.com/calamus/p/8569196.html
- nginx访问日志access_log
在 nginx.conf 配置文件 http{} 方法体的括号内,增加或者打开以下代码注释: log_format main '$remote_addr - $remote_user [$time_l ...
- 原生ajax实现文件上传
视图层 JS 函数: <input type="file" onchange="sendFile()" id="up" /> ...
- 常用的字符串方法 String ;
字符串: 1,str.charAt(num);//根据下标查找字符串中对应的字符,返回对应下标的字符; 2,str.charCodeAt(num);//字符串中下标对应的那位字符的 Unicode ...
- cobbler Ubuntu16.04 安装
cobbler vim /etc/debmirror.conf sed -i 's/@dists=\"sid\";/#@dists=\"sid\";/ ...
- WPF打字机效果
public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); TypewriteTex ...
- 常见WEB错误代码
404表示文件或资源未找到 java WEB常见的错误代码 1.1xx-信息提示:这些状态代码表示临时的响应.客户端在收到常规响应之前,应准备接收一个或多个1xx响应. 100-继续. 101-切换协 ...
- Qt之QTemporaryFile
简述 QTemporaryFile类是操作临时文件的I/O设备. QTemporaryFile用于安全地创建一个独一无二的临时文件.临时文件通过调用open()来创建,并且名称是唯一的(即:保证不覆盖 ...
- Windows下从源代码编译Skia
在PPAPI里面画图,能够结合第三方的图形库.比方Cairo.Skia. Google Chrome.Chromium和Android都使用Skia作为画图引擎.我也来试试Skia,先过编译关. fo ...
- Linux平台不同解压缩命令的使用方法
作者:郭孝星 微博:郭孝星的新浪微博 邮箱:allenwells@163.com 博客:http://blog.csdn.net/allenwells github:https://github.co ...