您的位置:首页 > 职场人生

Android面试系列文章2018之内存管理之Bitmap的加载篇

2018-02-26 21:44 351 查看

Android面试系列文章2018之内存管理之Bitmap的加载篇

1.recycle方法

  Bitmap在Android中内存存储位置有两块:

  1.native区(C区):必须调用Bitmap对象的recycle()方法才能对该Bitmap对象C区的内存进行回收。注意的是recycle执行是不可逆的,注意谨慎调用。

  2.Java区(自动回收)。

2.LRU(最近最少使用算法)

  它是怎么实现的?你可以这么回答:它是一个泛型类,它内部是有一个LinkedHashMap集合,内部提供了一个get和put方法来完成缓存的添加和获取操作,当缓存满的时候,你再往里面添加新的缓存对象的时候,它就会调用trimToSize这个方法把旧的并且使用次数少的缓存对象移除掉,然后再添加新的缓存对象。

3.计算inSampleSize

  加载图片时应该加载合适尺寸,分辨率大小等的图片,不可能每个位置都去加载原图,所以我们需要计算出某些显示图片的地方最合适尺寸,分辨率等大小的图片,这需要对inSampleSize进行计算,才能让图片做出合适的调整。当然也为了避免OOM异常。https://www.jianshu.com/p/f15cd2ed6ec0

public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int width = options.outWidth;
final int height = options.outHeight;
int inSampleSize = 1;

if (height > reqHeight || width > reqWidth) {
//计算图片高度和我们需要高度的最接近比例值
final int heightRatio = Math.round((float) height / (float) reqHeight);
//宽度比例值
final int widthRatio = Math.round((float) width / (float) reqWidth);
//取比例值中的较大值作为inSampleSize
inSampleSize = heightRatio > widthRatio ? heightRatio : widthRatio;
}

return inSampleSize;
}


  inSampleSize的默认值和最小值为1(当小于1时,解码器将该值当做1来处理),且在大于1时,该值只能为2的幂(当不为2的幂时,解码器会取与该值最接近的2的幂)。例如,当inSampleSize为2时,一个20001000的图片,将被缩小为1000500,相应地,它的像素数和内存占用都被缩小为了原来的1/4:

4.缩略图

public static Bitmap getThumbnail(Uri uri,int size, Context context) throws Exception {
InputStream input = context.getContentResolver().openInputStream(uri);

//配置BitmapFactory.Options,inJustDecodeBounds设为true,以获取图片的宽高
BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();
onlyBoundsOptions.inJustDecodeBounds = true;
onlyBoundsOptions.inDither=true;//optional
onlyBoundsOptions.inPreferredConfig=Bitmap.Config.ARGB_8888;//optional

//计算inSampleSize缩放比例
BitmapFactory.decodeStream(input, null, onlyBoundsOptions);
input.close();
if ((onlyBoundsOptions.outWidth == -1) || (onlyBoundsOptions.outHeight == -1))
return null;
int originalSize = (onlyBoundsOptions.outHeight > onlyBoundsOptions.outWidth) ? onlyBoundsOptions.outHeight : onlyBoundsOptions.outWidth;
double ratio = (originalSize > size) ? (originalSize / size) : 1.0;
//获取到缩放比例后,再次设置BitmapFactory.Options,获取图片缩略图
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inSampleSize = getPowerOfTwoForSampleRatio(ratio);
bitmapOptions.inDither=true;//optional
bitmapOptions.inPreferredConfig=Bitmap.Config.ARGB_8888;//optional
input = context.getContentResolver().openInputStream(uri);
Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);
input.close();
return bitmap;
}

/**
* 将double的比例采用近似值的方式转为int
* @param ratio
* @return
*/
private static int getPowerOfTwoForSampleRatio(double ratio){
int k = Integer.highestOneBit((int)Math.floor(ratio));
if(k==0) return 1;
else return k;
}


总体思想是通过设置BitmapFactory.Options.inJustDecodeBounds设为true,先获取到图片的宽高而并不会生产Bitmap;再通过所需图片的最长边size来获取缩放比例inSampleSize的值;

然后获所需尺寸的图片。

https://www.jianshu.com/p/d30c5e7d266d

5.三级缓存

a.网路

b.内存

c.本地

  总体思想就是为用户节约流量,当你在加载一张图片时,首先先判断本地是否已经缓存了该图片,如果没有,那么就通过网络进行加载,从网络加载的图片首先会存在与内存当中,为了节约用户的流量,可以将这张图片保存至本地,当用户退出程序或者某个操作导致这张图片被回收了,当用户某个操作又再试图加载这张图片的时候,此时由于本地已经缓存下来了,所以直接从本地把图片加载到内存当中并显示给用户即可。具体如何实现请看以下链接:

http://blog.csdn.net/u012325403/article/details/50388889
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 面试