如需转载请评论或简信,并注明出处,未经允许不得转载

目录

前言
内存抖动是由于短时间内有大量对象进出Young Generiation区导致的,它伴随着频繁的GC**
java不需要我们手动释放内存,它有自己的gc机制,所以gc的时机我们往往是不可控的。我们能做的,就是尽量避免会大量创建对象的操作
内存抖动的影响
gc会大量占用ui线程和cpu资源,会导致app卡顿
大多数的Android显示屏是以每秒60帧来刷新的。一帧可以看做是一张的独立的图片,60帧每秒就意味着,Android系统每隔16ms(1000ms/60Hz)就会进行一次渲染,如果这16ms内我们没有完成对视图的绘制,那么就会出现丢帧的情况
app流畅运行的情况(虽然也可能伴随着gc,但是在16ms内完成了绘制)

app卡顿的情况(gc占用ui线程的绘制时间,使得绘制时间超过16ms)

内存抖动的例子
之前看到一道题
把一个List里面的所有元素取出,通过“,”隔开,返回一个String
没有太多思考的情况下,可能会是下面这种实现方式
private String listToString(List<String> stringList) {
//先取第一个
String result = stringList.get(0);
for (int i = 1; i < stringList.size(); i++) {
//然后通过字符串累加的方式拼接字符串
result = result + "," + stringList.get(i);
}
return result;
}
我们知道,String是通过数组实现的,无法扩容,也就是说每次循环都会创建出一个新的String对象,当stringList的size比较大的时候,通过Profiler就会看到下面的情景,这就是内存抖动

我们可以通过StringBuilder把上面的代码优化一下
private String listToString(List<String> stringList) {
StringBuilder result = new StringBuilder();
result.append(stringList.get(0));
for (int i = 1; i < stringList.size(); i++) {
result.append("," + stringList.get(i));
}
return result.toString();
}
可以看到使用StringBuilder后内存变化相对较小且在较短的时间内就趋于平缓

不同的分代都有不同的垃圾回收算法,并不一定要等到老年代内存满了才会触发GC,如果频繁创建生命周期较短的对象,就会触发MinorGC,从而引发内存抖动
避免发生内存抖动的几点建议
-
尽量避免在循环体内创建对象,应该把对象创建移到循环体外
-
注意自定义View的onDraw()方法会被频繁调用,所以在这里面不应该频繁的创建对象
-
当需要大量使用Bitmap的时候,试着把它们缓存在数组中实现复用
-
对于能够复用的对象,可以使用对象池将它们缓存起来
网友评论