在准备面试,做笔记用,参考Android开发艺术探索
想真正了解这个问题最好买本书,静下心来细细看,因为除了这个方法,你还能看到一些更细节的东西,推荐参考任玉刚的Android开发艺术探索,除了加载大图片之外,还有关于内存缓存,磁盘缓存,最终实现一个加载图片的加载器。
1、实现途径:
加载图片的办法是通过Bitmap,即占位图来实现,通过BitmapFactory提供了四类方法:decodeFile、decodeResource、decodeStream、decodeByteArray(文件系统、资源、输入流、字节数组),decodeFile、decodeResource最终调用的也是decodeStream,底层是由几个native的方法实现。
2、原理方法:
假如我们通过ImageView展示图片,正常情况之下imageView的尺寸并没有图片那么大,此时就需要进行缩小。
(1)BitmapFactory中有一个重要的类是Options,此类用于解码Bitmap时的各种参数控制,inJustDecodeBounds参数设置为true时,Bitmap只会解析图片的宽跟高。不会去加载图片,对应outWidth、outHeigh。
(2)Options的inSampleSize参数,即采样率,当为1的时候,不进行缩放,采样率正常为2的n次幂,如果不为n次幂则往下取,如:3往下取为2,缩放为1/inSampleSize
(3)inJustDecodeBounds设置为false,此时采样率已经被修改过,在进行加载图片,加载的图片就不会出现OOM的状况。
3、图片大小计算方法:
(腾讯面试的时候遇到过,当时没接触过所以不会,只能面完马上补上)
Android中计算一张图片所占内存大小方法:图片长*宽*所占像素字节数,而像素字节数Android中也就四种,
1:ALPHA_8 占1个字节
2:ARGB_4444 占2个字节
3:ARGB_8888 占4个字节
4:RGB_565 占2个字节(不需要A的时候可以使用这一个,理解什么时候使用)
- public static int calculateInSampleSize(BitmapFactory.Options options,
- int reqWidth, int reqHeight) {
- // 源图片的高度和宽度
- final int height = options.outHeight;
- final int width = options.outWidth;
- 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 = heightRatio < widthRatio ? heightRatio : widthRatio;
- }
- return inSampleSize;
- }
- public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
- int reqWidth, int reqHeight) {
- // 第一次解析将inJustDecodeBounds设置为true,来获取图片大小
- final BitmapFactory.Options options = new BitmapFactory.Options();
- options.inJustDecodeBounds = true;
- BitmapFactory.decodeResource(res, resId, options);
- // 调用上面定义的方法计算inSampleSize值
- options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
- // 使用获取到的inSampleSize值再次解析图片
- options.inJustDecodeBounds = false;
- return BitmapFactory.decodeResource(res, resId, options);
- }