具有上下文的无内存泄漏单例
Memory-leak free Singleton with context
我正在尝试实现以下单例模式:SingletonClass.getInstance(context).callMethod()
虽然有各种教程解释如何在 Kotlin 中制作单例,但其中 none 解决了在静态字段中保存 context
会导致内存泄漏的事实 Android.
如何在不造成内存泄漏的情况下创建上述模式?
更新:
这是我对 CommonsWare 解决方案 #2 的实现。我用的是公币
单例class:
class NetworkUtils(val context: Context) {
}
申请Class:
class MyApplication : Application() {
val appModule = module {
single { NetworkUtils(androidContext()) }
}
override fun onCreate() {
super.onCreate()
startKoin(this, listOf(appModule))
}
}
Activity class:
class MainActivity : AppCompatActivity() {
val networkUtils : NetworkUtils by inject()
}
选项 #1:让 getInstance(Context)
在提供的 Context
上调用 applicationContext
并保留它。 Application
单例是在您的进程存在时创建的,并且在进程的生命周期内存在。它是预泄漏的;你不能再泄露了。
选项 #2:摆脱 getInstance()
并设置某种形式的依赖注入(Dagger 2、Koin 等)。这些 DI 框架有一些方法可以让它们向它们创建并注入下游的单例提供 Application
单例。
如果您必须创建涉及上下文的单例 class,您可以这样做。这会有所帮助。在这种情况下,当您调用 getInstance(context) 时,您的上下文将在每个 activity 中重置。
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;
}
}
当您第一次调用 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:
class MyApp: Application(){
override fun onCreate(){
PreferenceHelper.initWith(this)
}
}
以及以后在应用中的任何位置:
PreferenceHelper.someAction()
如果您不需要在每次使用 Singleton class 执行某些操作时都需要引用 Context
,则可以这样做。
我不会将上下文存储在 SingletonClass 中,我只是通过依赖注入将上下文传递给 class 的每个方法。
类似于:
SingletonClass.callMethod(context)
像这样在伴随对象中定义 "static" 方法:
companion object {
fun callMethod(context: Context) {
// do Something
}
}
然后从您的 activity 调用它:
SingletonClass.callMethod(this)
希望对您有所帮助:)
我正在尝试实现以下单例模式:SingletonClass.getInstance(context).callMethod()
虽然有各种教程解释如何在 Kotlin 中制作单例,但其中 none 解决了在静态字段中保存 context
会导致内存泄漏的事实 Android.
如何在不造成内存泄漏的情况下创建上述模式?
更新:
这是我对 CommonsWare 解决方案 #2 的实现。我用的是公币
单例class:
class NetworkUtils(val context: Context) {
}
申请Class:
class MyApplication : Application() {
val appModule = module {
single { NetworkUtils(androidContext()) }
}
override fun onCreate() {
super.onCreate()
startKoin(this, listOf(appModule))
}
}
Activity class:
class MainActivity : AppCompatActivity() {
val networkUtils : NetworkUtils by inject()
}
选项 #1:让 getInstance(Context)
在提供的 Context
上调用 applicationContext
并保留它。 Application
单例是在您的进程存在时创建的,并且在进程的生命周期内存在。它是预泄漏的;你不能再泄露了。
选项 #2:摆脱 getInstance()
并设置某种形式的依赖注入(Dagger 2、Koin 等)。这些 DI 框架有一些方法可以让它们向它们创建并注入下游的单例提供 Application
单例。
如果您必须创建涉及上下文的单例 class,您可以这样做。这会有所帮助。在这种情况下,当您调用 getInstance(context) 时,您的上下文将在每个 activity 中重置。
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;
}
}
当您第一次调用 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:
class MyApp: Application(){
override fun onCreate(){
PreferenceHelper.initWith(this)
}
}
以及以后在应用中的任何位置:
PreferenceHelper.someAction()
如果您不需要在每次使用 Singleton class 执行某些操作时都需要引用 Context
,则可以这样做。
我不会将上下文存储在 SingletonClass 中,我只是通过依赖注入将上下文传递给 class 的每个方法。 类似于:
SingletonClass.callMethod(context)
像这样在伴随对象中定义 "static" 方法:
companion object {
fun callMethod(context: Context) {
// do Something
}
}
然后从您的 activity 调用它:
SingletonClass.callMethod(this)
希望对您有所帮助:)