如何防止静态字段中上下文 class 引起的内存泄漏
How do I prevent memory leak caused by context class in static fields
求助!我漏水了(至少我是这么认为的...)
下面的 instance
值是我从静态伴随对象到这个 class 的“端口”。我有一些以某种方式使用 applicationContext 的想法(我的 TODO:评论)...因为我收到此内存泄漏警告...:[=14=]
为了避免这个问题,同时在每次调用这些函数时都不需要上下文参数(我想以某种方式将上下文存储在 class 中,并在它死亡时处理掉它), 这个问题有什么好的做法吗?
...
class Repository private constructor(
var context: Context
)
{
/**
* Repository class, class for all communication between database and external
* sources
* */
private val TAG = javaClass.simpleName
val appDatabase: AppDatabase = AppDatabase.getInstance(context.applicationContext)
//TODO: Test if better with applicationContext?
companion object {
private val TAG = this::class.java.simpleName
@Volatile private var instance:Repository ?=null
fun getInstance(context: Context)= instance
?: synchronized(this){
instance
?:Repository(context).also { instance = it }
}
fun liveDataUserResult(staffId: StaffType=StaffType.DRIVER) =
instance?.liveDataUserResult(staffId = staffId)
fun liveDataDepartmentResult(staffId: StaffType=StaffType.DRIVER) =
instance?.liveDataDepartmentResult(staffId = staffId)
...
fun liveDataGalleryItemSiteNoInUserPath() = instance?.liveDataGalleryItemSiteNoInUserPath()
...
}
fun liveDataGalleryItemSiteNoInUserPath() =
appDatabase.galleryItemDao().liveDataGalleryItemSiteNoInUserPath(allText = context.getString(R.string.repository_all_text))
}
除了直接传递 AppDatabase
实例外,不要在 Repository
中传递 Context
。
AppDatabase
在整个应用程序中用作 Singleton
所以你可能只在应用程序 class 或其他一些 Singleton
中启动它一次,然后使用相同的 Object
无处不在。
如果您使用任何依赖注入框架,如 Dagger2 或 Dagger-Hilt,create/inject 依赖将很容易。
您可以删除构造函数字段的 var 以使其工作,这样它就不会在全局范围内保留引用。感谢@Henry Twist .
class Repository private constructor(context: Context) {
private val TAG = javaClass.simpleName
var appDatabase: AppDatabase = AppDatabase.getInstance(context.applicationContext)
companion object {
@Volatile
private var instance: Repository? = null
@JvmStatic
fun getInstance(context: Context) = instance
?: synchronized(this) {
instance
?: Repository(context).also { instance = it }
}
}
}
以上所有感谢 ADM 和@Henry Twist 的出色回答(我已经接受),但我将post 我的结果放在这里:
class Repository private constructor(
context: Context
)
{
/**
* Repository class, class for all communication between database and external
* sources
* */
private val TAG = javaClass.simpleName
val applicationContext: Context = context.applicationContext
val appDatabase: AppDatabase = AppDatabase.getInstance(applicationContext)
companion object {
private val TAG = this::class.java.simpleName
@Volatile private var instance:Repository ?=null
fun getInstance(context: Context)= instance
?: synchronized(this){
instance
?:Repository(context).also { instance = it }
}
fun liveDataUserResult(staffId: StaffType=StaffType.DRIVER) =
instance?.liveDataUserResult(staffId = staffId)
fun liveDataDepartmentResult(staffId: StaffType=StaffType.DRIVER) =
instance?.liveDataDepartmentResult(staffId = staffId)
...
fun liveDataGalleryItemSiteNoInUserPath() = instance?.liveDataGalleryItemSiteNoInUserPath()
...
}
fun liveDataGalleryItemSiteNoInUserPath() =
appDatabase.galleryItemDao().liveDataGalleryItemSiteNoInUserPath(allText = applicationContext.getString(R.string.repository_all_text))
}
当然,Dagger2 或 Dagger-HILT 会更优雅。
求助!我漏水了(至少我是这么认为的...)
下面的 instance
值是我从静态伴随对象到这个 class 的“端口”。我有一些以某种方式使用 applicationContext 的想法(我的 TODO:评论)...因为我收到此内存泄漏警告...:[=14=]
为了避免这个问题,同时在每次调用这些函数时都不需要上下文参数(我想以某种方式将上下文存储在 class 中,并在它死亡时处理掉它), 这个问题有什么好的做法吗?
...
class Repository private constructor(
var context: Context
)
{
/**
* Repository class, class for all communication between database and external
* sources
* */
private val TAG = javaClass.simpleName
val appDatabase: AppDatabase = AppDatabase.getInstance(context.applicationContext)
//TODO: Test if better with applicationContext?
companion object {
private val TAG = this::class.java.simpleName
@Volatile private var instance:Repository ?=null
fun getInstance(context: Context)= instance
?: synchronized(this){
instance
?:Repository(context).also { instance = it }
}
fun liveDataUserResult(staffId: StaffType=StaffType.DRIVER) =
instance?.liveDataUserResult(staffId = staffId)
fun liveDataDepartmentResult(staffId: StaffType=StaffType.DRIVER) =
instance?.liveDataDepartmentResult(staffId = staffId)
...
fun liveDataGalleryItemSiteNoInUserPath() = instance?.liveDataGalleryItemSiteNoInUserPath()
...
}
fun liveDataGalleryItemSiteNoInUserPath() =
appDatabase.galleryItemDao().liveDataGalleryItemSiteNoInUserPath(allText = context.getString(R.string.repository_all_text))
}
除了直接传递 AppDatabase
实例外,不要在 Repository
中传递 Context
。
AppDatabase
在整个应用程序中用作 Singleton
所以你可能只在应用程序 class 或其他一些 Singleton
中启动它一次,然后使用相同的 Object
无处不在。
如果您使用任何依赖注入框架,如 Dagger2 或 Dagger-Hilt,create/inject 依赖将很容易。
您可以删除构造函数字段的 var 以使其工作,这样它就不会在全局范围内保留引用。感谢@Henry Twist .
class Repository private constructor(context: Context) {
private val TAG = javaClass.simpleName
var appDatabase: AppDatabase = AppDatabase.getInstance(context.applicationContext)
companion object {
@Volatile
private var instance: Repository? = null
@JvmStatic
fun getInstance(context: Context) = instance
?: synchronized(this) {
instance
?: Repository(context).also { instance = it }
}
}
}
以上所有感谢 ADM 和@Henry Twist 的出色回答(我已经接受),但我将post 我的结果放在这里:
class Repository private constructor(
context: Context
)
{
/**
* Repository class, class for all communication between database and external
* sources
* */
private val TAG = javaClass.simpleName
val applicationContext: Context = context.applicationContext
val appDatabase: AppDatabase = AppDatabase.getInstance(applicationContext)
companion object {
private val TAG = this::class.java.simpleName
@Volatile private var instance:Repository ?=null
fun getInstance(context: Context)= instance
?: synchronized(this){
instance
?:Repository(context).also { instance = it }
}
fun liveDataUserResult(staffId: StaffType=StaffType.DRIVER) =
instance?.liveDataUserResult(staffId = staffId)
fun liveDataDepartmentResult(staffId: StaffType=StaffType.DRIVER) =
instance?.liveDataDepartmentResult(staffId = staffId)
...
fun liveDataGalleryItemSiteNoInUserPath() = instance?.liveDataGalleryItemSiteNoInUserPath()
...
}
fun liveDataGalleryItemSiteNoInUserPath() =
appDatabase.galleryItemDao().liveDataGalleryItemSiteNoInUserPath(allText = applicationContext.getString(R.string.repository_all_text))
}
当然,Dagger2 或 Dagger-HILT 会更优雅。