具有上下文的无内存泄漏的Singleton

时间:2019-01-28 19:06:11

标签: android kotlin singleton android-context

我正在尝试实现以下单例模式: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()

}

4 个答案:

答案 0 :(得分:7)

选项#1:让getInstance(Context)在提供的applicationContext上呼叫Context并按住。 Application单例是在您的流程存在并在该流程的生命期内存在的时候创建的。它是预先泄漏的;您不能再泄漏它了。

选项2:摆脱getInstance()并设置某种形式的依赖项注入(Dagger 2,Koin等)。这些DI框架有一些方法可以使它们向其创建并向下游注入的单例提供Application单例。

答案 1 :(得分: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,则可以执行此操作。

答案 2 :(得分:0)

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

SingletonClass.callMethod(context)

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

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

然后通过以下活动从您的活动中调用它:

SingletonClass.callMethod(this)

希望它会有所帮助:)

答案 3 :(得分:-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;
  }
}