我的自定义处理程序类中发生了某些内存泄漏,但不确定如何解决。在线签出了一些示例,但是我的代码没有什么特别的,因此不确定如何进行操作:
private val startupCallback = object: RetryCallback(NUMBER, DELAY) {
override fun onRetry(retryCount: Int) {
mySdkApi.applicationStartup(this)
}
override fun onCompleted(): Boolean {
updateStatus(Callback.Status.StartUpSDK)
return true
}
override fun onFailed(e: MyException?) {
updateStatus(Callback.Status.StartUpSDK, "", e)
}
}
Android Studio不断提示“此处理程序类应该是静态的,否则可能会发生泄漏”。有什么主意吗?
答案 0 :(得分:2)
Android Studio抱怨很合理。问题在于匿名类会捕获对创建它们的父类的引用。
基本上有两种解决方法:“不美观”和“丑陋”。它们都与WeakReference有关。
#1 不太好的解决方案是创建一个需要较弱引用的类
class ApiRetryCallback(activity: Activity): RetryCallback(NUMBER, DELAY) {
private val weakActivity = WeakReference(activity)
override fun onRetry(retryCount: Int) {
weakActivity.get()!!.mySdkApi.applicationStartup(this) //or weakThis.get()? to swallow null cases
}
override fun onCompleted(): Boolean {
weakActivity.get()!!.updateStatus(Callback.Status.StartUpSDK)
return true
}
override fun onFailed(e: MyException?) {
weakActivity.get()!!.updateStatus(Callback.Status.StartUpSDK, "", e)
}
}
活动中:
private val startupCallback = ApiRetryCallback(this) //this is MainActivity here
#2 丑陋的解决方案基于以下事实:lambda只能在直接使用它的情况下捕获父引用。因此,我想出了这种替代方法,但在调试器中没有看到强引用,但是您应该检查一下:
private val startupCallback = {
val weakActivity = WeakReference(this@MainActivity)
object : RetryCallback(NUMBER, DELAY) { //returned as last expression
override fun onRetry(retryCount: Int) {
weakActivity.get()!!.mySdkApi.applicationStartup(this) //or weakThis.get()? to swallow null cases
}
//....else methods....
}
}()
在这里,lambda将立即被调用,并且将仅捕获对象内部的弱引用,并且还将返回直到object为止的最后一个表达式。
#3 在撰写本文时,我想出了第三个解决方案,该解决方案接近#2
private val startupCallback = WeakReference(this).let { //this here is MainActivity
val weakActivity = it //it of let scope wich is WeakReference
object : RetryCallback(NUMBER, DELAY) { //returned as last expression
override fun onRetry(retryCount: Int) {
weakActivity.get()!!.mySdkApi.applicationStartup(this) //or weakThis.get()? to swallow null cases
}
//....else methods....
}
}
答案 1 :(得分:0)
匿名类(如您的类)不是静态的。您可以将匿名类替换为普通类(只需创建扩展RetryCallback的类),然后将所有需要的对象作为构造函数参数传递。