在写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