引导页图片一般采用本地图片打包在APK中,并且显示大小为整个屏幕,所以在显示引导页图片时有以下几点需要注意:
1. 最好使用多个尺寸的引导页来保证适配效果,比如在drawable-hdpi, drawable-xhdpi和drawable-xxhdpi里各放一套图。
2. 为了控制包的大小,图片大小要适当控制
3. 优先使用BitmapFactory.createBitmap来解析引导页获取bitmap,因为通过该方法我们可以控制bitmap的大小正好匹配引导页需要显示的大小,这样可以在保证显示效果的情况下,尽可能的少占用内存以降低OOM的概率。
示例如下
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的值,这样可以保证最终图片的宽和高
// 一定都会大于等于目标的宽和高。
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);
}
遇到的坑:
1. 直接使用setImageRes()来显示,viewpager在显示view的过程中会频繁创建销毁view,导致drawable的频繁创建引起oom
2. 使用UIL来显示加载,其一加载缓慢(UIL不建议被用来加载本地图片),其二内存回收不及时,当引导页销毁时,其bitmap已不再需要,但是不能手动recycle
改进:
自己解析本地图片,保存bitmap并缓存,当使用viewpager显示时,使用缓存的bitmap。当页面销毁时清除缓存的bitmap