Android - 强引用和弱引用在开发中的应用

241 阅读2分钟

引用类型概述

Java 提供了四种引用类型(从强到弱):

  1. 强引用 (Strong Reference)
  2. 软引用 (Soft Reference)
  3. 弱引用 (Weak Reference)
  4. 虚引用 (Phantom Reference)

1. 软引用 (SoftReference)

软引用是一种相对强引用弱化了一些的引用,主要用于内存敏感的缓存。

特点:

  • 当内存不足时,软引用对象可能被回收
  • 内存充足时,软引用对象不会被回收
  • 适合用来实现内存敏感的缓存

示例代码:

class ImageCache {
    private val cache = mutableMapOf<String, SoftReference<Bitmap>>()
    
    fun putBitmap(key: String, bitmap: Bitmap) {
        cache[key] = SoftReference(bitmap)
    }
    
    fun getBitmap(key: String): Bitmap? {
        val softReference = cache[key]
        return softReference?.get()
    }
}

实际应用场景:

  1. 图片缓存
class ImageLoader {
    private val memoryCache = mutableMapOf<String, SoftReference<Bitmap>>()
    
    fun loadImage(url: String, imageView: ImageView) {
        // 先从缓存中查找
        val cachedBitmap = memoryCache[url]?.get()
        if (cachedBitmap != null) {
            imageView.setImageBitmap(cachedBitmap)
            return
        }
        
        // 异步加载图片
        coroutineScope.launch {
            val bitmap = downloadImage(url)
            memoryCache[url] = SoftReference(bitmap)
            imageView.setImageBitmap(bitmap)
        }
    }
}

2. 弱引用 (WeakReference)

弱引用比软引用更弱,只要垃圾回收器运行,若只有弱引用指向该对象,就会被回收。

特点:

  • 生命周期更短
  • 下一次 GC 时一定会被回收
  • 适合用来防止内存泄漏

示例代码:

class MyHandler(activity: Activity) {
    private val activityRef: WeakReference<Activity> = WeakReference(activity)
    
    fun handleMessage(msg: Message) {
        val activity = activityRef.get()
        activity?.let {
            // 使用 activity 进行操作
        }
    }
}

实际应用场景:

  1. Handler 防止内存泄漏:
class MainActivity : AppCompatActivity() {
    private val myHandler = object : Handler(Looper.getMainLooper()) {
        private val weakReference = WeakReference(this@MainActivity)
        
        override fun handleMessage(msg: Message) {
            val activity = weakReference.get() ?: return
            // 处理消息
        }
    }
}
  1. 观察者模式中防止内存泄漏:
class EventManager {
    private val listeners = mutableListOf<WeakReference<EventListener>>()
    
    fun addListener(listener: EventListener) {
        listeners.add(WeakReference(listener))
    }
    
    fun notifyListeners() {
        listeners.removeAll { it.get() == null }  // 清理已被回收的引用
        listeners.forEach { 
            it.get()?.onEvent()
        }
    }
}
  1. Fragment 引用:
class MyFragment : Fragment() {
    private var callback: WeakReference<Callback>? = null
    
    fun setCallback(callback: Callback) {
        this.callback = WeakReference(callback)
    }
    
    private fun onSomeEvent() {
        callback?.get()?.onCallback()
    }
}

实践建议

  1. 缓存策略选择

    • 对于内存敏感的缓存,使用 SoftReference
    • 需要及时释放的对象引用,使用 WeakReference
  2. 防止内存泄漏

    // 在 Activity 中使用异步任务
    class LongRunningTask(activity: Activity) {
        private val activityRef = WeakReference(activity)
        
        fun execute() {
            GlobalScope.launch {
                // 长时间操作
                withContext(Dispatchers.Main) {
                    activityRef.get()?.updateUI()
                }
            }
        }
    }
    
  3. 生命周期管理

    class ViewModel {
        private var view: WeakReference<View>? = null
        
        fun attachView(view: View) {
            this.view = WeakReference(view)
        }
        
        fun detachView() {
            view = null
        }
    }
    

注意事项

  1. 及时清理

    • 定期清理无效的弱引用
    • 使用 WeakHashMap 等集合类自动处理弱引用
  2. 合理使用

    • 不要过度使用弱引用
    • 某些场景直接使用强引用更合适
  3. 性能考虑

    • 频繁创建和销毁引用对象可能影响性能
    • 合理设计缓存策略
  4. 引用队列

    val referenceQueue = ReferenceQueue<Activity>()
    val weakReference = WeakReference(activity, referenceQueue)
    
    // 处理被回收的引用
    val polled = referenceQueue.poll()
    

通过合理使用软引用和弱引用,可以有效地管理内存,防止内存泄漏,实现更健壮的 Android 应用程序。