一句话说透Android里面的内存抖动

93 阅读2分钟

一句话总结:
内存抖动就像在派对上狂造垃圾,清洁工(GC)来回疯跑扫垃圾,结果大家卡在原地等打扫,派对卡成PPT!


一、什么是内存抖动?

  • 官方解释:  频繁创建大量临时对象 → 触发GC疯狂回收 → 导致UI卡顿。
  • 人话翻译:  你一边疯狂造垃圾(new对象),一边逼着清洁工(GC)不停地扫,清洁工扫得越勤,大家(主线程)越得站着等,App就卡成狗!

二、经典作死案例(看看你中招没?)

案例1:在onDraw()里疯狂new对象(自杀式代码)

override fun onDraw(canvas: Canvas) {  
    val paint = Paint() // 每次绘制都new新Paint!找死!
    paint.color = Color.RED  
    canvas.drawCircle(100f, 100f, 50f, paint)  
}

后果:  屏幕每秒刷新60次 → 每秒创建60个Paint对象 → GC直接抽风!

案例2:ListView/RecyclerView适配器里瞎搞

override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {  
    val view = View.inflate(context, R.layout.item, null) // 不复用convertView!
    val text = "Item " + position + "次" // 疯狂拼接字符串!
    view.textView.text = text  
    return view  
}

后果:  快速滑动列表时 → 每秒生成几百个View和String → 内存炸出烟花!


三、如何避免内存抖动?(保命指南)

1. 口诀:能重用就别new!(对象池大法好)

  • 优化onDraw():
// 提前初始化,全局只一个Paint!
private val paint = Paint().apply {  
    color = Color.RED  
}  

override fun onDraw(canvas: Canvas) {  
    canvas.drawCircle(100f, 100f, 50f, paint) // 爽!不再new对象!
}
  • 优化适配器:复用ConvertView!
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {  
    val view = convertView ?: View.inflate(context, R.layout.item, null) // 复用!  
    view.textView.text = "Item $position" // 用模板字符串,别拼接!  
    return view  
}

2. 别在循环里搞事情!
作死代码:

fun calculateSum(list: List<Int>): Int {  
    var sum = 0  
    for (i in 0 until list.size) {  
        val item = list[i] // 每次循环都访问list[i],其实可以优化!  
        sum += item  
    }  
    return sum  
}

优化代码:

fun calculateSum(list: List<Int>): Int {  
    var sum = 0  
    for (item in list) { // 直接用迭代,避免多次get()  
        sum += item  
    }  
    return sum  
}

3. 字符串拼接用StringBuilder!
作死代码:

var result = ""  
for (i in 0..10000) {  
    result += i.toString() // 每次拼接都new新String!  
}

保命代码:

val builder = StringBuilder()  
for (i in 0..10000) {  
    builder.append(i)  
}  
val result = builder.toString()

四、查内存抖动的神器(Android Profiler)

  1. 打开Android Studio → 底部 Profiler → 点 Memory
  2. 操作你的App → 看内存曲线是否像“锯齿山”(频繁上升下降)
  3. 点击 Record 抓取内存分配 → 找出哪个类在疯狂创建对象!

五、总结

  • 内存抖动的本质:  临时对象太多 → GC加班 → 主线程罚站!
  • 保命口诀:
    “重用对象是王道,循环里面别瞎闹,字符串用Builder搞,onDraw()里别new爆!”