侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1823 篇文章
  • 累计收到 0 条评论

Android中避免内存泄漏的常见方法

2025-12-12 / 0 评论 / 4 阅读

题目

Android中避免内存泄漏的常见方法

信息

  • 类型:问答
  • 难度:⭐

考点

内存泄漏原理,Context引用管理,匿名内部类使用

快速回答

避免Android内存泄漏的核心方法:

  • 避免静态变量持有Context:使用Application Context代替Activity Context
  • 及时解注册监听器:在onDestroy()中解除广播、回调等绑定
  • 谨慎使用非静态内部类:改用静态内部类+WeakReference
  • 关闭耗时资源:及时释放Cursor、FileStream等资源
## 解析

1. 原理说明

内存泄漏指对象不再被使用时仍被GC Root引用,导致无法被垃圾回收。在Android中常见于:

  • 生命周期错配:长生命周期对象持有短生命周期对象(如Activity)
  • 未释放资源:广播、监听器、IO流等未及时关闭
  • 内部类隐式引用:非静态内部类默认持有外部类引用

2. 常见场景与解决方案

场景1:静态变量持有Activity引用

错误代码示例:

public class MyUtils {
    private static Context sContext; // 危险!

    public static void init(Context context) {
        sContext = context; // 若传入Activity会导致泄漏
    }
}

修复方案:

  • 使用Application Context:sContext = context.getApplicationContext()
  • WeakReference包装:
    private static WeakReference<Context> sContextRef;

场景2:未解注册监听器

错误代码示例:

public class MainActivity extends Activity {
    private SensorManager sensorManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        sensorManager.registerListener(sensorListener); // 注册监听
    }

    // 缺少onDestroy解注册
}

修复方案:

@Override
protected void onDestroy() {
    super.onDestroy();
    sensorManager.unregisterListener(sensorListener); // 必须解注册
}

场景3:Handler导致泄漏

危险代码:

private Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        // 隐式持有Activity引用
    }
};

安全方案:

// 1. 静态内部类 + WeakReference
private static class SafeHandler extends Handler {
    private final WeakReference<MainActivity> mActivity;

    SafeHandler(MainActivity activity) {
        mActivity = new WeakReference<>(activity);
    }

    @Override
    public void handleMessage(Message msg) {
        MainActivity activity = mActivity.get();
        if (activity != null) {
            // 安全操作
        }
    }
}

// 2. 在onDestroy清除消息
@Override
protected void onDestroy() {
    super.onDestroy();
    mHandler.removeCallbacksAndMessages(null);
}

3. 最佳实践

  • 使用LeakCanary库自动检测内存泄漏
  • 遵循谁注册谁解注册原则
  • 对Bitmap等大对象使用recycle()
  • 避免在循环中创建临时对象

4. 常见错误

  • 在Fragment中直接使用getActivity()而不检查null
  • 在AsyncTask中直接操作UI组件
  • 使用匿名内部类作为回调(改用静态内部类)

5. 扩展知识

  • GC Root类型:静态变量、线程栈变量、JNI引用等
  • 内存分析工具:Android Profiler, MAT工具
  • 常见泄漏场景:单例模式、动画未取消、WebView等