5月29日 23:47
Android 内存泄漏有哪些常见场景?如何检测和避免?
Android 内存泄漏本质是对象生命周期结束了,却还被 GC Roots 间接引用,导致无法回收。高频场景有:静态变量持有 Activity、非静态 Handler 或匿名内部类持有外部类、监听器/广播未注销、线程或网络请求未取消、Cursor/IO 流未关闭、集合缓存长期保存 View 或 Context。检测优先用 LeakCanary 看引用链,复杂问题再用 Android Studio Memory Profiler 抓 Heap Dump。避免原则很简单:谁注册谁注销,谁启动谁取消,长生命周期对象不要持有短生命周期 Context。
追问
为什么静态变量持有 Activity 会泄漏?
静态变量生命周期接近进程,Activity 销毁后如果仍被它引用,GC 无法回收整个 Activity 以及关联 View 树。需要 Context 时优先传 applicationContext。
Handler 为什么容易泄漏?
非静态内部 Handler 会隐式持有 Activity,消息队列里的 Message 又持有 Handler。Activity 销毁后消息没执行完,就会延长 Activity 生命周期。
LeakCanary 主要看什么?
重点看泄漏对象到 GC Root 的引用链,找到第一个不该长期持有它的对象。不要只看类名,要结合页面生命周期判断是不是误报。
项目里怎么避免监听器泄漏?
在 onStart/onStop 或 onCreate/onDestroy 成对注册和注销。使用 LifecycleObserver、协程 lifecycleScope、Flow repeatOnLifecycle 可以减少手动清理遗漏。
写段代码
javastatic class SafeHandler extends Handler { private final WeakReference<Activity> ref; SafeHandler(Activity activity) { ref = new WeakReference<>(activity); } @Override public void handleMessage(Message msg) { Activity a = ref.get(); if (a == null || a.isFinishing()) return; } } @Override protected void onDestroy() { handler.removeCallbacksAndMessages(null); super.onDestroy(); }