Kotlin 辅助对象 class 内存泄漏
Kotlin helper object class memory leak
我想创建一个辅助对象来帮助我从项目的任何位置访问字符串。这个辅助对象也应该在单元测试中工作。但是我不能确定是否存在内存泄漏的风险,例如使用?
这是辅助对象。
object ResourceHelper {
private var getString: (Int) -> String = {
it.toString()
}
private var getStringWithArgs: (Int, Array<out Any>) -> String = { id, args ->
"$id${args.contentToString()}"
}
fun getString(@StringRes id: Int): String {
return getString.invoke(id)
}
fun getString(@StringRes id: Int, vararg args: Any): String {
return getStringWithArgs.invoke(id, args)
}
fun initialize(resources: Resources) {
getString = { id -> resources.getString(id) }
getStringWithArgs = { id, args -> resources.getString(id, *args) }
}
}
这是项目中唯一的activity。
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
ResourceHelper.initialize(resources)
}
}
这是视图模型class,我不太了解引用是如何保存在堆栈中的。这种做法有什么问题吗?
class MyViewModel : ViewModel() {
fun printString(id: Int) {
val s = ResourceHelper.getString(id)
Log.d("*****", s)
}
}
由于配置更改,Activity 每次启动时 Activity 的 Resources 对象都是不同的。
您的代码将在 Activity 被销毁和下一次重新创建之间暂时泄漏 Resources 对象(在 onCreate()
中,当您再次调用 initialize()
并且覆盖通过引用持有的 Resources 对象)。如果那只是方向改变期间的时间,那是微不足道的。但是,如果是在用户退出 Activity 和他们下次 return 到该应用程序之间的时间段内,那么您的应用程序将占用比必要更多的内存。
无论如何,像这样的状态控制单例使单元测试变得困难。我建议创建扩展函数作为替代方法。如果您需要在 ViewModel 中访问字符串资源,您可以从 AndroidViewModel 扩展,它可以通过应用程序访问资源。
fun AndroidViewModel.getString(@StringRes id: Int) =
getApplication<Application>().resources.getString(id)
fun AndroidViewModel.getString(@StringRes id: Int, vararg args: Any) =
getApplication<Application>().resources.getString(id, args)
我想创建一个辅助对象来帮助我从项目的任何位置访问字符串。这个辅助对象也应该在单元测试中工作。但是我不能确定是否存在内存泄漏的风险,例如使用?
这是辅助对象。
object ResourceHelper {
private var getString: (Int) -> String = {
it.toString()
}
private var getStringWithArgs: (Int, Array<out Any>) -> String = { id, args ->
"$id${args.contentToString()}"
}
fun getString(@StringRes id: Int): String {
return getString.invoke(id)
}
fun getString(@StringRes id: Int, vararg args: Any): String {
return getStringWithArgs.invoke(id, args)
}
fun initialize(resources: Resources) {
getString = { id -> resources.getString(id) }
getStringWithArgs = { id, args -> resources.getString(id, *args) }
}
}
这是项目中唯一的activity。
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
ResourceHelper.initialize(resources)
}
}
这是视图模型class,我不太了解引用是如何保存在堆栈中的。这种做法有什么问题吗?
class MyViewModel : ViewModel() {
fun printString(id: Int) {
val s = ResourceHelper.getString(id)
Log.d("*****", s)
}
}
由于配置更改,Activity 每次启动时 Activity 的 Resources 对象都是不同的。
您的代码将在 Activity 被销毁和下一次重新创建之间暂时泄漏 Resources 对象(在 onCreate()
中,当您再次调用 initialize()
并且覆盖通过引用持有的 Resources 对象)。如果那只是方向改变期间的时间,那是微不足道的。但是,如果是在用户退出 Activity 和他们下次 return 到该应用程序之间的时间段内,那么您的应用程序将占用比必要更多的内存。
无论如何,像这样的状态控制单例使单元测试变得困难。我建议创建扩展函数作为替代方法。如果您需要在 ViewModel 中访问字符串资源,您可以从 AndroidViewModel 扩展,它可以通过应用程序访问资源。
fun AndroidViewModel.getString(@StringRes id: Int) =
getApplication<Application>().resources.getString(id)
fun AndroidViewModel.getString(@StringRes id: Int, vararg args: Any) =
getApplication<Application>().resources.getString(id, args)