
1) 【一句话结论】Android内存泄漏常见源于静态引用、内部类、异步任务/Handler未清理、资源未释放等,需通过合理管理对象引用(如弱引用、及时释放资源)避免,例如图片加载用LruCache+弱引用缓存,数据缓存用LRU策略并定期清理过期数据,防止因引用未释放导致内存占用过高。
2) 【原理/概念讲解】内存泄漏是指对象被引用但不再被使用,导致垃圾回收器(GC)无法回收,从而占用内存。类比:房间里的“客人”被“门未关”的引用锁住,即使其他人都离开,这个客人仍占着房间,导致房间(内存)无法被重新分配。常见原因包括:
3) 【对比与适用场景】
| 类别 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| 强引用 | 直接引用对象 | 对象不会被GC回收 | 普通对象,需长期存在 | 可能导致内存泄漏 |
| 弱引用 | 对象可能被GC回收 | 对象可被回收,引用随时失效 | 缓存(如图片、数据),避免泄漏 | 需处理null,对象可能随时消失 |
| 静态引用 | 类的静态变量引用对象 | 生命周期与类一致 | 需跨实例共享的常量或工具类 | 必须手动清理,否则泄漏 |
4) 【示例】(图片加载场景):
假设学而思APP中图片加载使用自定义LruCache,代码伪代码:
// 创建LruCache,用WeakReference缓存图片
public class ImageCache {
private LruCache<String, WeakReference<Bitmap>> cache;
public ImageCache(int maxSize) {
int memorySize = Runtime.getRuntime().maxMemory() / 8;
cache = new LruCache<>(memorySize);
}
public Bitmap get(String url) {
WeakReference<Bitmap> ref = cache.get(url);
Bitmap bitmap = ref == null ? null : ref.get();
if (bitmap == null) {
// 加载图片逻辑(如Glide加载)
bitmap = loadBitmap(url);
cache.put(url, new WeakReference<>(bitmap));
}
return bitmap;
}
// 当图片不再显示时,缓存自动清理(WeakReference特性)
}
当Activity销毁时,图片不再显示,WeakReference的Bitmap会被GC回收,缓存自动清理,避免内存泄漏。
5) 【面试口播版答案】
“内存泄漏常见原因包括静态引用、内部类、Handler未清理、资源未释放等。比如学而思APP图片加载时,若用强引用缓存图片,图片对象会被一直持有,导致内存占用过高。我们可以用LruCache结合WeakReference,缓存图片时用弱引用,当图片不再被Activity引用时,GC会回收Bitmap,缓存自动清理。另外,Handler的message队列若未在Activity销毁时移除,也会导致引用泄漏,需在onDestroy中调用removeCallbacksAndClearQueue()。总结来说,关键是通过弱引用管理缓存,及时清理Handler消息,避免静态成员持有Activity引用,从而防止内存泄漏。”
6) 【追问清单】
WeakReference包装需要缓存的图片对象,当图片不再被强引用持有时,WeakReference的get()会返回null,缓存自动清理。bitmap.recycle(),并在不再使用时释放内存,避免Bitmap占用内存。7) 【常见坑/雷区】
removeCallbacksAndClearQueue(),导致Handler引用泄漏。recycle(),导致Bitmap占用内存。