单例应只持有Application Context或使用弱引用避免内存泄漏:构造时禁用Activity等短生命周期Context,缓存UI对象需用WeakReference,静态内部类须配合WeakReference,SDK初始化应强制使用getApplicationContext()并及时反注册。

关键在于切断单例对 Activity 或其他短生命周期 Context 的强引用,确保它只持有与自身生命周期一致的 Application Context,或通过弱引用、延迟绑定等方式规避持有关系。
始终使用 Application Context 初始化单例
Activity 或 Service 的 Context 生命周期远短于单例,一旦传入就会造成泄漏。正确做法是在构造单例时只接收 Application Context:
- 在 getInstance() 方法中统一调用
context.getApplicationContext(),而非直接保存传入的 context - 避免在单例构造函数中接受 Activity.this、this(Activity 内部)、getBaseContext() 等易变上下文
- 如果初始化入口在 Activity 中,应先获取 application context:
getApplicationContext(),再传给单例
不直接持有短生命周期对象的强引用
即使不传 Context,单例若缓存了 Activity、Fragment、View、Listener 等对象,同样会阻止其回收:
- 如需临时关联 UI 组件,改用 WeakReference<Activity> 存储,访问前判空
- 禁止将 Activity 实例、匿名内部类(如 OnClickListener)作为单例字段长期保存
- 对必须持有的回调接口,提供 clear() 或 onDestroy() 回调机制,由外部主动解绑
警惕静态变量 + 非静态内部类组合
这类写法隐蔽但高危:静态变量延长了内部类生命周期,而内部类又隐式持有外部 Activity 引用:
- 避免在 Activity 内定义
private static Handler handler = new Handler(){...} - 非静态内部类(如自定义 Runnable、Callback)不应被静态变量引用
- 改用静态内部类 + WeakReference<Activity>,或直接使用外部类定义的静态 Handler
检查第三方 SDK 和监听注册逻辑
部分 SDK 在初始化时会要求传入 Context,若内部未做 ApplicationContext 转换,也可能引发泄漏:
- 查阅 SDK 文档,确认其是否支持传入 getApplicationContext()
- 在单例中封装 SDK 初始化逻辑,并强制使用 Application Context
- 若 SDK 提供 register/unregister 接口(如广播、传感器、Lifecycles),务必在 Activity/Fragment 销毁时反向调用

















