Kotlin单例中安全存储Android Context的方案咨询
解决Kotlin单例SDK存储Context的内存泄漏问题
直接将Context存储在Kotlin object单例的变量中会触发内存泄漏警告,原因是单例的生命周期和应用一致,如果持有Activity/Fragment这类组件级别的Context,会导致组件无法被GC回收,进而引发内存泄漏。以下是几种可行的替代方案:
1. 存储Application Context
这是最推荐的方案,Application Context属于全局上下文,生命周期和应用完全一致,不会因组件销毁而引发泄漏。
object Sdk { private var appContext: Context? = null fun init(context: Context) { this.appContext = context.applicationContext } // 对外提供上下文的方法(可选) fun getAppContext(): Context? = appContext }
调用context.applicationContext即可获取全局上下文,后续SDK内部所有需要Context的操作都使用这个实例。
2. 使用弱引用(WeakReference)
如果确实需要持有组件级别的Context(如Activity),可以用WeakReference包装,它不会阻止GC回收被引用的对象,避免内存泄漏。
import java.lang.ref.WeakReference object Sdk { private var contextRef: WeakReference<Context>? = null fun init(context: Context) { contextRef = WeakReference(context) } // 使用时先获取有效Context,注意判空 fun getContext(): Context? { return contextRef?.get() } }
注意:使用前必须检查Context是否为null,因为当组件被销毁后,WeakReference.get()会返回null。SDK开发中尽量避免这种场景,优先用Application Context。
3. 依赖注入(DI)框架管理
借助Hilt、Dagger等DI框架,让框架自动管理Application Context的生命周期,无需手动存储,代码更简洁且不易出错。
以Hilt为例:
import dagger.hilt.android.HiltAndroidApp import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject import javax.inject.Singleton // 先在Application类添加Hilt注解 @HiltAndroidApp class MyApplication : Application() // 用@Singleton标记SDK类,通过构造注入获取Application Context @Singleton class Sdk @Inject constructor( @ApplicationContext private val appContext: Context ) { // SDK业务方法直接使用appContext即可 fun doSomething() { appContext.getString(R.string.some_string) } }
这种方式下,DI框架会自动提供全局上下文,并确保SDK实例的生命周期和应用一致,彻底避免手动持有Context带来的泄漏风险。
注意事项
- 优先选择Application Context,这是Android SDK开发的标准实践,绝大多数场景都能满足需求。
- 除非有临时的组件级需求,否则不要持有Activity/Fragment的Context。
- 复杂架构的SDK或应用,推荐使用DI框架管理依赖,提升代码可维护性。
内容的提问来源于stack exchange,提问作者WISHY
相关产品推荐
相关产品推荐

