1. 匿名内部类 / 非静态内部类持有外部类引用
js
void testHttpRequest(Activity activity) {
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(10000); // 模拟耗时操作
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
问题:
匿名 Runnable 默认持有 activity 的引用,如果这段代码在 Activity 销毁后还在运行,就会导致 Activity 无法被 GC。
解决方式:
使用弱引用:
js
void testHttpRequest(WeakReference<Activity> weakReference) {
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Activity activity = weakReference.get();
if (activity != null) {
// 安全使用 activity
}
}
}).start();
}
2. Handler 导致的泄漏
js
public class MyActivity extends Activity {
Handler handler = new Handler();
void startTask() {
handler.postDelayed(() -> {
// 执行某些操作
}, 10000);
}
}
问题:
非静态 Handler 自动持有 Activity 的引用,导致泄漏。
解决方式
js
@Override
protected void onDestroy() {
handler.removeCallbacksAndMessages(null); // 清空队列
super.onDestroy();
}
手动清空消息队列
总结
当异步任务或延迟执行的代码中隐式或显式地引用了 Activity,而这些任务的生命周期超过了 Activity 本身,就可能导致 Activity 无法被 GC 回收,形成内存泄漏。
3. 单例或静态变量持有 Context
js
public class AppManager {
private static Context context;
public static void init(Context ctx) {
context = ctx;
}
}
问题:
如果传入的是 Activity
或 View
,会因持久持有导致内存泄漏。
解决方式:
只保存 ApplicationContext