Android结合volley的netWorkImageview实现图片文件缓存

在写Android应用程序时经常会用到图片缓存,对于网络请求使用Android平台上的网络通信库Volley,能使网络通信更快,更简单,更健壮,而且Volley特别适合数据量不大但是通信频繁的场景,所以可以使用volley来请求网络图片。接下来就将本人在一个项目中的图片缓存模块拿出来跟大家分享,欢迎批评指正。

/**
 * @author
 * @date 2015/4/14
 * 利用文件缓存图片
 */

public class ImageFileCacheUtils {
	private static final String CHCHEDIR = "ImageChace";//缓存目录
	private static final String WHOLESALE_CONV = ".cache";//缓存文件后缀名
	private static final int MB = 1024 * 1024;
	private static final int CACHE_SIZE = 80;//缓存最大容量(超过就会利用lru算法删除最近最少使用的缓存文件)
	private static final int FREE_SD_SPACE_NEEDED_TO_CACHE = 100;//缓存所需SD卡所剩的最小容量

	private static ImageFileCacheUtils instance = null;
	//单例模式
	public static ImageFileCacheUtils getInstance(){
		if (instance == null) {
			synchronized (ImageFileCacheUtils.class) {
				if (instance == null) {
					instance = new ImageFileCacheUtils();
				}
			}
		}
		return instance;
	}

	public ImageFileCacheUtils(){
		removeCache(getDirectory());
	}

	/**
	 * 从文件缓存中获取图片
	 * @param url
	 * @return
	 */
	public Bitmap getImage(final String url){
		final String path = getDirectory() + "/" +convertUrlToFileName(url);
		File file = new File(path);
		if(file.exists()){
			Bitmap bitmap = BitmapFactory.decodeFile(path);
			if(bitmap == null){
				file.delete();
				return null;
			}else {
				updateFileTime(path);//更新文件最新访问时间
				return bitmap;
			}
		}else {
			return null;
		}
	}

	/**
	 * 获得缓存目录
	 * @return
	 */
	private String getDirectory() {
		String dir = getSDPath() + "/" + CHCHEDIR;
		return dir;
	}

	private String getSDPath(){
		File sdDir = null;
		boolean adCardExit = Environment.getExternalStorageState()
				.endsWith(Environment.MEDIA_MOUNTED);//判断SD卡是否挂载
		if (adCardExit) {
			sdDir = Environment.getExternalStorageDirectory();//获取根目录
		}
		if (sdDir != null) {
			return sdDir.toString();
		}else {
			return "";
		}
	}

	/**
	 * 修改文件的最后修改时间
	 * @param path
	 */
	private void updateFileTime(String path) {
		File file = new File(path);
		long newModeifyTime = System.currentTimeMillis();
		file.setLastModified(newModeifyTime);
	}

	public void saveBitmap(Bitmap bitmap,String url){
		if (bitmap == null) {
			return ;
		}
		//判断SD卡上的空间
		if(FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()){
			return;
		}
		String fileName = convertUrlToFileName(url);
		String dir = getDirectory();
		File dirFile = new File(dir);
		if (!dirFile.exists()) {
			dirFile.mkdirs();
		}
		File file = new File(dir + "/" +fileName);
		try {
			file.createNewFile();
			OutputStream outputStream = new FileOutputStream(file);
			bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
			outputStream.flush();
			outputStream.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 计算sd卡上的剩余空间
	 * @return
	 */
	private int freeSpaceOnSd() {
		StatFs statFs = new StatFs(Environment.getExternalStorageDirectory().getPath());
		double sdFreeMB = ((double)statFs.getAvailableBlocks() * (double)statFs.getBlockSize()) / MB;
		Log.i("test", "剩余空间为:"+sdFreeMB);
		return (int)sdFreeMB;
	}

	/**
	 * 将url转成文件名
	 * @param url
	 * @return
	 */
	private String convertUrlToFileName(String url) {
		String[] strs = url.split("/");
		return strs[strs.length - 1] + WHOLESALE_CONV;
	}

	/**
	 * 计算存储目录下的文件大小
	 * 当文件总大小大于规定的大小或者sd卡剩余空间小于FREE_SD_SPACE_NEEDED_TO_CACHE的规定时
	 * ,那么删除40%最近没有被使用的文件
	 * @param dirPath
	 * @return
	 */
	private boolean removeCache(String dirPath){
		File dirFile = new File(dirPath);
		File[] files = dirFile.listFiles();
		if (files == null || files.length <= 0) {
			return true;
		}
		//如果sd卡没有挂载
		if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
			return false;
		}
		int dirSize = 0;
		for (int i = 0; i < files.length; i++) {
			if (files[i].getName().contains(WHOLESALE_CONV)) {
				dirSize += files[i].length();
			}
		}
		if (dirSize > CACHE_SIZE * MB || FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) {
			int removeFactor = (int)((0.4 * files.length) + 1);
			Arrays.sort(files, new FileLastModifySoft());
			for (int i = 0; i < removeFactor; i++) {
				if (files[i].getName().contains(WHOLESALE_CONV)) {
					files[i].delete();
				}
			}
		}
		if (freeSpaceOnSd() <= CACHE_SIZE) {
			return false;
		}
		return true;
 	}

	//比较器类
	private class FileLastModifySoft implements Comparator<File>{
		@Override
		public int compare(File arg0, File arg1) {
			if (arg0.lastModified() > arg1.lastModified()) {
				return 1;
			}else if (arg0.lastModified() == arg1.lastModified()) {
				return 0;
			}else {
				return -1;
			}
		}
	}
}

利用volley的networkImageview加载图片时需要传入一个ImageLoader,在构造ImageLoader时需要一个实现ImageCache接口的类,所以先构造此类:

public class ImageFileCache implements ImageCache{

	@Override
	public Bitmap getBitmap(String url) {
		return ImageFileCacheUtils.getInstance().getImage(url);
	}

	@Override
	public void putBitmap(String url, Bitmap bitmap) {
		ImageFileCacheUtils.getInstance().saveBitmap(bitmap, url);
	}

}

接下来使用networkImageview加载网络图片:

在布局文件中使用volley的自定义组件:

<com.android.volley.toolbox.NetworkImageView
                android:id="@+id/activity_icon"
                android:layout_width="@dimen/activity_icon_size_w"
                android:layout_height="@dimen/activity_icon_size_h"
                android:layout_marginRight="4dp"
                android:scaleType="centerInside"
                android:src="@drawable/activity_example" />
<pre name="code" class="java" style="color: rgb(85, 85, 85); font-size: 14px; line-height: 26px; orphans: 2; widows: 2;">//初始化imageLoader
ImageLoader imageLoader = new ImageLoader(Volley.newRequestQueue(context), new ImageFileCache());
activity_icon.setDefaultImageResId(R.drawable.activity_example);
activity_icon.setErrorImageResId(R.drawable.activity_example);
<pre name="code" class="java" style="color: rgb(85, 85, 85); font-size: 14px; line-height: 26px; orphans: 2; widows: 2;">holder.activity_icon.setImageUrl(a.getLogo(), imageLoader);



此模块可以直接使用在自己的项目中,希望可以帮助大家。

版权声明:本文为博主原创文章,需要转载,请以链接形式注明出处。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-05 00:41:38

Android结合volley的netWorkImageview实现图片文件缓存的相关文章

android开发里跳过的坑——图片文件上传失败

使用的apache的httpclient的jar包,做的http图片上传,上传时,服务器总返文件格式不对.后来发现,是由于在创建FileBody时,使用了默认的ContentType引起的.所以服务器有判断文件类型的要求的时候,创建FlieBody时需要注意添加MIME类型,例如PNG图片文件: new FileBody(entity.getValue(), ContentType.create("IMAGE/PNG")));

【第六篇】Volley代码修改之图片二级缓存以及相关源码阅读(重现ImageLoader.ImageCache)

前面http://www.cnblogs.com/androidsuperman/p/8a157b18ede85caa61ca5bc04bba43d0.html 有讲到使用LRU来处理缓存的,但是只是处理内存里面的缓存,没进行文件缓存和处理,那么如何实现Volley在本地的缓存呢 一般硬盘缓存使用com.jakewharton.disklrucache.DiskLruCache这个Lru缓存,具体代码在 https://github.com/JakeWharton/DiskLruCache/tr

使用.htaccess进行浏览器图片文件缓存

对于图片类网站,每次打开页面都要重新下载图片,慢不说,还非常浪费流量.这时就需要用到缓存,强制浏览器缓存图片文件 缓存文件,提问网站访问数度,减少流量消耗,现提供2中缓存代码 打开.htaccess文件,写入下面代码 方法一:统一缓存时长 <FilesMatch ".(flv|gif|jpg|jpeg|png|ico|txt|swf|pdf|swf|js)$"> Header set Cache-Control "max-age=2592000" <

android 开发怎么让程序生成的图片文件不会被系统扫描到

我们在写应用的时候,可能会保存很多图片,大的小的,仅仅是我们的应用中会用到,处于种种原因不希望用户看到,我是觉着如果被用户看到了,就失去了我的应用的那一层神秘的面纱,用户是米有闲情逸致去打开你一层层的文件夹去翻看你保存图片或者音视频等多媒体文件的.但是很多像图库看图软件或者音乐播放器视频播放器在播放本地音视频的时候会扫描用户的文件系统,就会把你保存的多媒体文件扫出来.       这时候如果你保存的小图片太多,或者小段的音频太多,用户在翻过了好多页之后,满屏幕的还是你的应用里边的东西可能会引起用

Android之简单了解Bitmap显示图片及缓存图片

昨天我们学了如何连接网络,今天我们就学习一下如何从把网上图片显示到项目中 今天主要用到的是Bitmap 类 Bitmap是Android系统中的图像处理的最重要类之一.用它可以获取图像文件信息,进行图像剪切.旋转.缩放等操作,并可以指定格式保存图像文件 具体作用属性参考官方API: https://msdn.microsoft.com/zh-cn/library/system.drawing.bitmap(v=vs.110).aspx 不多说,看案例吧 做一个图片显示器: activity_ma

服务器基于PHP CodeIgniter,Android基于Volley实现多文件/图片上传(含服务器,web版和android客户端完整代码)

问题背景:app在上传图片时,同时传递参数,支持传递多个图片.本文中的环境默认已经配好了服务器的CodeIgniter框架.事实上不使用这个框架也是可以的. 一,服务器部分 1,在controllers下的helpers新建文件upload_helper.php <?php /** * Make multifile array input complaint with CI_Upload.<br> * For use files[ ] input name you must use it

Android利用Volley异步加载数据(JSON和图片)完整示例

Android利用Volley异步加载数据(JSON和图片)完整示例 MainActivity.java package cc.testvolley; import org.json.JSONObject; import android.app.Activity; import android.app.ProgressDialog; import android.graphics.Bitmap; import android.os.Bundle; import android.support.v

如何将位置信息写入JPEG图片文件【android】

通过ExifInterface可以将拍照时的一些属性信息写入图片文件里,其中包括经纬度信息.本文介绍一种将经纬度坐标写入JPEG图片文件的方法! 核心代码 /** * 浮点型经纬度值转成度分秒格式 * * @param coord * @return */ public String decimalToDMS(double coord) { String output, degrees, minutes, seconds; // gets the modulus the coordinate d

[Android] 针对生成的图片文件在系统Gallery不显示的处理

之前遇到过一个问题,就是发现我在程序中生成一个新的 Bitmap 之后,当我打开系统的 Gallery 查看时,并没有看到新生成的图像.然而打开文件浏览器,找到保存 Bitmap 所在的文件夹下,还能看到程序生成的 Bitmap 文件.也就是说,文件其实存在,但 Gallery 似乎并没有刷新.之后,又一个新的行为证实了我的观点,即,每次重启设备之后, Gallery 中就会显示新生成的 Bitmap 了.也就是说,重启设备之后,系统对某个保存有图片信息的文件进行了重新读写(当时得出的是这么个结