具有上下文的内存泄漏单例

问题描述 投票:2回答:4

我正在尝试实现以下单例模式:SingletonClass.getInstance(context).callMethod()

虽然有各种各样的教程解释如何在Kotlin中制作单例,但它们都没有解决在静态字段中持有context会导致Android内存泄漏的事实。

如何在不创建内存泄漏的情况下创建上述模式?

更新:

这是我对CommonsWare解决方案#2的实现。我用过Koin。

单身人士课程:

class  NetworkUtils(val context: Context) {

}

申请类别:

class MyApplication : Application() {

    val appModule = module {
        single { NetworkUtils(androidContext()) }
    }

    override fun onCreate() {
        super.onCreate()
        startKoin(this, listOf(appModule))
    }
}

活动类:

class MainActivity : AppCompatActivity() {

    val networkUtils : NetworkUtils by inject()

}
android kotlin singleton android-context
4个回答
8
投票

选项#1:让getInstance(Context)在提供的applicationContext上调用Context并持有它。 Application单身人士是在你的过程过程中为这个过程的生命而生活的。它是预先泄露的;你不能进一步泄漏它。

选项#2:摆脱getInstance()并设置某种形式的依赖注入(Dagger 2,Koin等)。有这些DI框架的配方,让它们将Application单例提供给它们创建并向下游注入的单体。


0
投票

当您第一次调用getInstance()时,传递给此函数的Context将永久保存。因此,进一步getInstance()调用的上下文没有任何关系。我永远不会保存这个Context

这就是我在做的事情:

在Kotlin中创建一个object,并在应用程序启动后立即使用上下文初始化对象。我没有存储上下文,而是执行该上下文所需的任何操作。

object PreferenceHelper {

    private var prefs: SharedPreferences? = null

    fun initWith(context: Context){
        if(prefs == null) this.prefs = context.getSharedPreferences("prefs", Context.MODE_PRIVATE)
    }

    fun someAction(){ .... }
}

Application类内:

class MyApp: Application(){
   override fun onCreate(){
      PreferenceHelper.initWith(this)
   }
 }

以及以后应用中的任何地方:

 PreferenceHelper.someAction()

如果每次使用Singleton类执行某些操作时不需要引用Context,则可以执行此操作。


0
投票

我不会将上下文存储在SingletonClass中,我只是通过依赖注入将上下文传递给类的每个方法。就像是:

SingletonClass.callMethod(context)

在配对对象中定义“静态”方法,如下所示:

 companion object {
        fun callMethod(context: Context) {
            // do Something
        }
    }

然后从您的活动中调用它:

SingletonClass.callMethod(this)

希望它有帮助:)


-1
投票

如果你必须创建包含上下文的单例类,你可以这样做。这会有所帮助。在这种情况下,当您调用getInstance(context)时,将在每个活动中重置您的上下文。

public class MyClass {

    private Context context;

    public static getInstance(Context context){
         if(instance ==null)
             instance = new MyClass();
         instance.setContext(context);
         return instance;
    }

   public void setContext(Context context){
      this.context = context;
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.