ImageView.setImageResource(resId) OOM和滑动卡顿
那是为什么,会导致oom呢:
原来当使用像 imageView.setBackgroundResource,imageView.setImageResource, 或者 BitmapFactory.decodeResource 这样的方法来设置一张大图片的时候,
这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存。
因此,改用先通过BitmapFactory.decodeStream方法,创建出一个bitmap,再将其设为ImageView的 source,decodeStream最大的秘密在于其直接调用JNI>>nativeDecodeAsset()来完成decode,无需再使用java层的createBitmap,从而节省了java层的空间。如果在读取时加上图片的Config参数,可以跟有效减少加载的内存,从而跟有效阻止抛out of Memory异常。
另外,需要特别注意:
decodeStream是直接读取图片资料的字节码了, 不会根据机器的各种分辨率来自动适应,使用了decodeStream之后,需要在hdpi和mdpi,ldpi中配置相应的图片资源,否则在不同分辨率机器上都是同样大小(像素点数量)
解决方法:
第一种,弃用
imageView.setImageResource(resId)
采用图片加载框架进行加载,解决内存溢出和卡顿问题,推荐(Glide,imageLoader)
第二种,自己对图片先进行网络在线压缩,第二把png转化为jpg,同样的图片 png 要比jpg的大很多,自行对设置图片格式RGB-565,然后隔行取点, 减少内存中的图片大小。方法如下
@Override
protected void onStop() {
super.onStop();
if (btp!=null){
btp.recycle();
}
}
/**
* 大图片处理机制
* 利用Bitmap 转存 R图片
*/
public static Bitmap btp;
public void getBitmapForImgResourse(Context mContext, int imgId, ImageView mImageView) throws IOException {
InputStream is = mContext.getResources().openRawResource(imgId);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = false;
options.inPreferredConfig = Bitmap.Config.RGB_565;
options.inPurgeable = true;
options.inInputShareable = true;
options.inSampleSize = 1;
btp = BitmapFactory.decodeStream(is, null, options);
mImageView.setImageBitmap(btp);
// btp.recycle();
is.close();
}
HorizontalScrollView 卡顿 RecyclerView
网上有人说禁止RecyclerView的滑动。
,滑动嵌套避免有点卡顿
GifImageView卡顿,其实是一样的
Android LayoutInflater.inflate卡顿
LayoutInflater将xml文件实例化为一个view对象的流程
我们会发现,其中有两个部分是耗时的主要来源
XmlResourseParser对xml的遍历
反射创建View对象导致的耗时
这两点,又跟Xml的复杂程度成正相关,Xml越复杂,则递归调用所消耗的时间就越长,就产生了我们所说的,卡顿问题,反射比直接创建对象要慢3倍,iReader的x2c框架就是基于这一点去做的优化
简化布局的层级;include和merge结合使用;ViewStub 按需加载;减少使用wrap_content,最好使用固定宽高或者match_parent,减少计算;ConstraintLayout使用等。
另外还有其他的优化手段:如AsyncLayoutInflater异步加载布局。笔者使用这种方式解决了LayoutInflater.inflate的ANR问题。此外我们还可以在super.onCreate之前使用LayoutInflaterCompat.setFactory2来监控控件加载耗时。