Android性能优化主要分几个方面
- 图片加载
- 数据库操作
- Http请求
- UI优化
- 代码好习惯
图片加载
app在加载较大Bitmap的时候经常会包OOM异常,反复改变一个控件的图片或者加载太多图片到内存的时候会报OOM;原因如下,android给每个app开辟的运行内存是固定的,有的是16MB,有的更多,具体根据手机而定,而当大图片被加载到内存之后可能导致内存超过了android系统给定的内存,这时候就报OOM,或者反复加载一个小图片,例如反复调用BitmapFactory.decodeResource()方法加载xml文件,而xml文件里面定义的可能是按钮的点击图片效果,反复的加载也会导致内存溢出;
解决方案:加载大的图片可以优先加载缩略图,网上找的代码;
public class BitmapUtils {
private 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 halfHeight = height / 2;
final int halfWidth = width / 2;
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
// 如果是放大图片,filter决定是否平滑,如果是缩小图片,filter无影响
private static Bitmap createScaleBitmap(Bitmap src, int dstWidth,
int dstHeight) {
Bitmap dst = Bitmap.createScaledBitmap(src, dstWidth, dstHeight, false);
if (src != dst) { // 如果没有缩放,那么不回收
src.recycle(); // 释放Bitmap的native像素数组
}
return dst;
}
// 从Resources中加载图片
public static Bitmap decodeSampledBitmapFromResource(Resources res,
int resId, int reqWidth, int reqHeight) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options); // 读取图片长款
options.inSampleSize = calculateInSampleSize(options, reqWidth,
reqHeight); // 计算inSampleSize
options.inJustDecodeBounds = false;
Bitmap src = BitmapFactory.decodeResource(res, resId, options); // 载入一个稍大的缩略图
return createScaleBitmap(src, reqWidth, reqHeight); // 进一步得到目标大小的缩略图
}
// 从sd卡上加载图片
public static Bitmap decodeSampledBitmapFromFd(String pathName,
int reqWidth, int reqHeight) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(pathName, options);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inJustDecodeBounds = false;
Bitmap src = BitmapFactory.decodeFile(pathName, options);
return createScaleBitmap(src, reqWidth, reqHeight);
}
}
可以把常用的图片(例如按钮点击效果图片等)事先加载到内存中,在退出界面的时候再进行回收,因为这些图片较小,如果反复加载的话上一次加载的图片还在内存中没释放,下一次还加载相同的图片,有可能造成内存溢出,我就遇到过这种情况:我在之前的项目中反复调用BitmapFactory.decodeResource(),然后就OOM了,后来把图片资源事先缓存到内存中就ok了;
采用多级图片缓存,在内存中缓存图片,在sdk卡中缓存图片,一般很多图片加载的三方库都是采用多级缓存,充分利用LruCache这篇博客对于LruCache有一个比较清晰的解释,关于图片的缓存还可以去阅读图片缓存的第三方库的源码,学习它们是如果实现图片的高效的缓存的,比如说:picasso,ImageLoader,其实可以直接选择第三方库来实现开发中的图片缓存
未完待续。。。