Android面试系列文章2018之内存管理之Bitmap的加载篇
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中的内存溢出和内存泄漏问题
- android Cache——webview的缓存处理
- Android:这是一份全面&详细的 热修复 学习指南
- android动态加载ClassLoader机制
- Android中如何把bitmap存成BMP格式的图片
- android使用.9,png图片作为背景的问题
- android UI之Shape详解_GradientDrawable
- Android(安卓)ListView中复杂数据流的高效渲染
- Android(安卓)LazyList 从网络获取图片并缓存