51mee - AI智能招聘平台Logo
模拟面试题目大全招聘中心会员专区

在Android开发中,内存泄漏的常见原因有哪些?结合好未来学而思APP中图片加载或数据缓存的使用场景,请举例说明如何避免内存泄漏?

好未来前端 - Android难度:中等

答案

1) 【一句话结论】Android内存泄漏常见源于静态引用、内部类、异步任务/Handler未清理、资源未释放等,需通过合理管理对象引用(如弱引用、及时释放资源)避免,例如图片加载用LruCache+弱引用缓存,数据缓存用LRU策略并定期清理过期数据,防止因引用未释放导致内存占用过高。

2) 【原理/概念讲解】内存泄漏是指对象被引用但不再被使用,导致垃圾回收器(GC)无法回收,从而占用内存。类比:房间里的“客人”被“门未关”的引用锁住,即使其他人都离开,这个客人仍占着房间,导致房间(内存)无法被重新分配。常见原因包括:

  • 静态成员持有Context/Activity引用:静态变量属于类,生命周期与类一致,若静态成员持有Activity引用,即使Activity被销毁,静态引用仍存在,导致Activity无法被GC回收。
  • 内部类/匿名内部类持有外部类引用:内部类通过this指向外部类实例,若外部类被GC回收,内部类引用仍存在,导致内存泄漏。
  • 异步任务/Handler未正确清理:Handler的message队列或looper可能持有Activity/Context引用,若任务未在onDestroy时移除消息或关闭Handler,会导致引用泄漏。
  • 资源未释放:如图片Bitmap未调用recycle(),数据库连接未关闭,文件流未释放,导致资源占用内存。

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) 【追问清单】

  • 追问1:如何处理静态成员持有Activity的引用?
    回答要点:在Activity的onDestroy或onStop中,将静态引用置为null,并调用GC强制回收(注意:GC不保证立即回收,但可提示)。
  • 追问2:弱引用在缓存中具体如何实现?
    回答要点:使用WeakReference包装需要缓存的图片对象,当图片不再被强引用持有时,WeakReference的get()会返回null,缓存自动清理。
  • 追问3:图片Bitmap的内存泄漏如何避免?
    回答要点:加载图片后及时调用bitmap.recycle(),并在不再使用时释放内存,避免Bitmap占用内存。
  • 追问4:内存泄漏检测工具有哪些?
    回答要点:Android Studio的Memory Profiler、LeakCanary库(需集成),用于检测内存泄漏。

7) 【常见坑/雷区】

  • 静态成员持有Activity引用:忘记在Activity销毁时清理,导致Activity无法被GC回收。
  • Handler的message队列未清理:在Activity销毁时未调用removeCallbacksAndClearQueue(),导致Handler引用泄漏。
  • 弱引用使用不当:缓存时未用WeakReference,导致对象无法被GC回收。
  • 图片Bitmap未recycle:加载图片后未调用recycle(),导致Bitmap占用内存。
  • 缓存大小设置不合理:LruCache设置过大,导致内存占用过高;或过小,导致缓存频繁失效。
51mee.com致力于为招聘者提供最新、最全的招聘信息。AI智能解析岗位要求,聚合全网优质机会。
产品招聘中心面经会员专区简历解析Resume API
联系我们南京浅度求索科技有限公司admin@51mee.com
联系客服
51mee客服微信二维码 - 扫码添加客服获取帮助
© 2025 南京浅度求索科技有限公司. All rights reserved.
公安备案图标苏公网安备32010602012192号苏ICP备2025178433号-1