Bitmap高效加载、Cache和优化(一)
2016-09-10 21:42
316 查看
Bitmap在Android开发中经常会用到,高效加载Bitmap就显得很重要了,节省流量,加快加载速度,不出现卡顿现象这是我们想要达到的目的。
Android常用的缓存策略也是很重要的,Bitmap也需要做缓存,主要有两种,内存缓存和存储缓存,当请求加载图片时,先从内存缓存中找,找不到就到存储缓存中找,在存储缓存中也没有就从网络加载。缓存主要使用的是Lru算法,即是最近最少使用算法 ,当缓存不足的时候,会淘汰近期最少使用的缓存。常用的缓存有LruCache和DiskLruCache,LruCache用作内存缓存,DiskLruCache用作存储缓存。
一、Bitmap高效加载
加载图片,BitmapFactory有四个方法:decodeFile,decodeResource,decodeStream,decodeByteArray,分别从文件、资源、输入流、字节数组中加载Bitmap对象。
想要高效加载需要采用BitmapFactory.Options,通过BitmapFactory.Options可以按一定比例来加载缩小后的图片,将缩小的图片在imageView中显示,可以降低内存占用还可以避免OOM(内存溢出)。
缩放图片主要参数是inSampleSize是采样率,即是缩小多少倍,当他是大于1 的整数时才有缩小的效果,当小于等于1时,无缩小效果,例如inSampleSize == 2时,图片的长宽都缩小为原来的1/2,整个图片就相当是原来的 1/4 ,图片缩放率是 1/n 的。最新官方文档要求是inSampleSize是2的N次方,如果不是系统会选择最接近的2的N次方代替。
高效加载步骤:
1. 将BitmapFactory.Options的inJustDecodeBounds设置为true并加载图片
2.获取图片原始的宽高,对应outWidth和outHeight
3.计算inSampleSize
4.inJustDecodeBounds设置为false,重新加载该图片
inJustDecodeBounds设为true会解析图片原始宽高但是不会真正加载图片
代码是《Android开发艺术探究》中提供的
二、内存缓存
内存中加载图片比存储中加载要快,内存缓存提高效率节省流量
缓存包括添加、获取、修改
前面说到了内存缓存常用的策略是LruCache,这个是泛型类,内部采用的是LinkedHashMap,提供了get和put方法完成获取和添加,并且他是线程安全的
重写sizeOf方法计算缓存对象大小,maxMemory是当前进程可用内存,一些特殊情况下还要重写entryRemoved完成资源回收工作。
获取缓存对象 mMemoryCache.get(key);
添加缓存对象 mMemoryCache.put(key,bitmap);
现在LruCache已经是源码一部分了,可直接使用
至于DiskLruCache存储缓存,咱们下一篇继续
Android常用的缓存策略也是很重要的,Bitmap也需要做缓存,主要有两种,内存缓存和存储缓存,当请求加载图片时,先从内存缓存中找,找不到就到存储缓存中找,在存储缓存中也没有就从网络加载。缓存主要使用的是Lru算法,即是最近最少使用算法 ,当缓存不足的时候,会淘汰近期最少使用的缓存。常用的缓存有LruCache和DiskLruCache,LruCache用作内存缓存,DiskLruCache用作存储缓存。
一、Bitmap高效加载
加载图片,BitmapFactory有四个方法:decodeFile,decodeResource,decodeStream,decodeByteArray,分别从文件、资源、输入流、字节数组中加载Bitmap对象。
decodeFile(String PathName);//指定文件解析创建 decodeFileDescriptor(FileDescriptor fd);//从FileDescriptor解析创建Bitmap decodeResource(Resource res,int id);//给定资源id解析创建 decodeStream(inputStream is);//从输入流中解析创建 decodeByteArray(byte[] data,int offset,int length);//从offset开始将length对象解析成Bitmap对象
想要高效加载需要采用BitmapFactory.Options,通过BitmapFactory.Options可以按一定比例来加载缩小后的图片,将缩小的图片在imageView中显示,可以降低内存占用还可以避免OOM(内存溢出)。
缩放图片主要参数是inSampleSize是采样率,即是缩小多少倍,当他是大于1 的整数时才有缩小的效果,当小于等于1时,无缩小效果,例如inSampleSize == 2时,图片的长宽都缩小为原来的1/2,整个图片就相当是原来的 1/4 ,图片缩放率是 1/n 的。最新官方文档要求是inSampleSize是2的N次方,如果不是系统会选择最接近的2的N次方代替。
高效加载步骤:
1. 将BitmapFactory.Options的inJustDecodeBounds设置为true并加载图片
2.获取图片原始的宽高,对应outWidth和outHeight
3.计算inSampleSize
4.inJustDecodeBounds设置为false,重新加载该图片
inJustDecodeBounds设为true会解析图片原始宽高但是不会真正加载图片
代码是《Android开发艺术探究》中提供的
public class ImageResizer { private static final String TAG = "ImageResizer"; public ImageResizer() { } public Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) { // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res, resId, options); } public Bitmap decodeSampledBitmapFromFileDescriptor(FileDescriptor fd, int reqWidth, int reqHeight) { // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFileDescriptor(fd, null, options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; return BitmapFactory.decodeFileDescriptor(fd, null, options); } public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { if (reqWidth == 0 || reqHeight == 0) { return 1; } // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; Log.d(TAG, "origin, w= " + width + " h=" + height); int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2; final int halfWidth = width / 2; // Calculate the largest inSampleSize value that is a power of 2 and // keeps both // height and width larger than the requested height and width. while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) { inSampleSize *= 2; } } Log.d(TAG, "sampleSize:" + inSampleSize); return inSampleSize; } }
二、内存缓存
内存中加载图片比存储中加载要快,内存缓存提高效率节省流量
缓存包括添加、获取、修改
前面说到了内存缓存常用的策略是LruCache,这个是泛型类,内部采用的是LinkedHashMap,提供了get和put方法完成获取和添加,并且他是线程安全的
//这是LruCache定义 public class LruCache<K,V>{ private final LinkedHashMap<K,V> map; .... }
<pre name="code" class="plain">这是LruCache初始化过程
int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); int cacheSize = maxMemory / 8; mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { @Override protected int sizeOf(String key, Bitmap bitmap) { return bitmap.getRowBytes() * bitmap.getHeight() / 1024; } };
重写sizeOf方法计算缓存对象大小,maxMemory是当前进程可用内存,一些特殊情况下还要重写entryRemoved完成资源回收工作。
获取缓存对象 mMemoryCache.get(key);
添加缓存对象 mMemoryCache.put(key,bitmap);
现在LruCache已经是源码一部分了,可直接使用
至于DiskLruCache存储缓存,咱们下一篇继续
相关文章推荐
- Bitmap高效加载、Cache和优化(二)
- Android Bitmap的加载优化与Cache相关介绍
- Bitmap的高效加载和 Cache
- Bitmap高效加载和Cache(一)
- 基于android示例程序(bitmapfun) 高效加载图片让人无语地方
- 【Android Training - Graphics】高效地显示Bitmap图片(Lesson 4 - 优化Bitmap的内存使用)
- 高效的加载大Bitmap(位图)
- 高效地显示Bitmap图片 1 - 有效率地加载大尺寸的位图
- 【Google官方教程】第一课:高效的加载大Bitmap(位图)
- 高效地加载大Bitmap(位图)
- Anroid高效显示Bitmap图片,减少OOM问题,加载大尺寸位图
- 【Google官方教程】第一课:高效的加载大Bitmap(位图)
- 高效使用Bitmaps(二) 后台加载Bitmap
- 关于android示例程序(bitmapfun)——高效加载图片的坑爹地方
- 【Google官方教程】第一课:高效地加载大Bitmap(位图)
- 【Google官方教程】第一课:高效地加载大Bitmap(位图)
- 第一课:高效地加载大Bitmap(位图)
- 译:Google官方教程】高效的加载大Bitmap(位图)
- 【Google官方教程】第一课:高效地加载大Bitmap(位图)
- 【Google官方教程】第一课:高效地加载大Bitmap(位图)