Android应用内存优化技巧

Trudy676 +0/-0 0 0 正常 2025-12-24T07:01:19 Android · Kotlin · 内存优化

Android应用内存优化技巧踩坑记录

最近在优化一个Android应用的内存使用时,踩了不少坑,分享一下实战经验。

问题背景

项目中出现了频繁的OOM(Out of Memory)异常,特别是在图片加载和列表滚动时。通过Android Profiler分析发现,Bitmap内存占用过高,GC频繁触发。

踩坑过程

1. Bitmap内存泄漏

最初以为是图片加载的问题,但实际排查发现是Bitmap没有及时回收导致的内存泄漏。

错误代码:

// 这样做会导致内存泄漏
fun loadImage(url: String, imageView: ImageView) {
    val bitmap = BitmapFactory.decodeStream(url.openStream())
    imageView.setImageBitmap(bitmap)
}

正确做法:

fun loadImage(url: String, imageView: ImageView) {
    // 使用WeakReference避免内存泄漏
    val bitmap = decodeSampledBitmapFromResource(url, 100, 100)
    imageView.setImageBitmap(bitmap)
    // 及时回收
    bitmap.recycle()
}

private fun decodeSampledBitmapFromResource(
    resId: Int, reqWidth: Int, reqHeight: Int
): Bitmap {
    // 首先设置inJustDecodeBounds为true来获取图片尺寸
    val options = BitmapFactory.Options().apply {
        inJustDecodeBounds = true
    }
    BitmapFactory.decodeResource(resources, resId, options)
    
    // 计算缩放比例
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight)
    options.inJustDecodeBounds = false
    return BitmapFactory.decodeResource(resources, resId, options)
}

2. RecyclerView ViewHolder未正确复用

在列表数据更新时,没有及时清理ViewHolder中的资源。

踩坑代码:

override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
    holder.imageView.loadImage(data[position].imageUrl)
    // 没有清理之前的图片加载任务
}

优化方案:

override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
    // 清理之前的加载任务
    holder.imageView.clear()
    holder.imageView.loadImage(data[position].imageUrl)
}

// 在ViewHolder中添加清理方法
inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    fun clear() {
        imageView.setImageDrawable(null)
        // 清理图片加载任务
    }
}

3. 使用WeakReference处理监听器

在Activity/Fragment中注册了多个监听器,没有及时注销导致内存泄漏。

错误做法:

// 监听器持有Activity引用
button.setOnClickListener { 
    // 处理逻辑
}

正确方案:

private val clickListener = View.OnClickListener { 
    // 处理逻辑
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    button.setOnClickListener(clickListener)
}

override fun onDestroy() {
    super.onDestroy()
    button.setOnClickListener(null)
}

总结

内存优化需要从多个维度入手,包括Bitmap处理、资源回收、监听器管理等。建议在开发过程中使用Android Profiler定期监控内存使用情况,及时发现问题。

关键点总结:

  1. Bitmap加载时注意缩放和回收
  2. RecyclerView ViewHolder及时清理资源
  3. 监听器注册后记得注销
  4. 使用WeakReference避免强引用
  5. 定期使用Profiler监控内存使用
推广
广告位招租

讨论

0/2000