所以我对 kotlin 和 Android 都很陌生。 我写了一个应用程序,它完全按照我想要的方式工作,除了 它给了我一个编译器警告:
'Do not place Android context classes in static fields; this is a memory leak'
在我的一个文件中:
lateinit var appContext: Context private set
lateinit var appRez: Resources private set
class HackJob : Application() {
override fun onCreate() {
super.onCreate()
appContext = applicationContext
appRez = resources
val clientthread = ClientThread() //these three can be collapsed into one line
val maThread = Thread(clientthread)
maThread.start()
}
internal class ClientThread : Runnable {
ContextCompat.getMainExecutor(appContext).execute /* command = */ {
MainActivity.otv.setBackgroundColor(Color.RED)
MainActivity.osb.visibility = View.VISIBLE
}
}
}
在另一个文件中:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// create a value that is linked to a button called (id) start in the layout
val tv: TextView = findViewById(R.id.rcvdData)
val startButton = findViewById<Button>(R.id.start)
...
otv = tv
osb = startButton
...
}
companion object {
lateinit var otv: TextView
lateinit var osb: Button
}
}
正如我所说,即使屏幕旋转,它似乎也能正常工作。 完全按照我想要的方式做!
我真的在这里泄漏内存了吗? 我应该对泄漏警告有多担心?
当我旋转屏幕时,大概 android 正在拆除 Activity,并且 重新实例化它旋转,但我的同伴变量(otv 和 osb)在 onCreate 中更新!这是否意味着旧值会失去引用计数并被GCed?
我承认我不太明白我在做什么,我只是不断尝试直到成功为止。 这段代码的味道有多糟糕?该应用程序非常敏捷并且运行良好!
即使屏幕旋转,它似乎也能正常工作
有问题。
我真的在这里泄漏内存了吗?
是的。对于您问题中的文字代码的影响很小,但如果您打算更改该代码,这种影响可能会变得更糟。
当我旋转屏幕时,大概 android 正在拆除该 Activity,并重新实例化它旋转,但我的同伴变量(otv 和 osb)在 onCreate 中更新!这是否意味着旧值会失去引用计数并被GCed?
是的。但是,请记住,除了配置更改之外,还有其他方法可以销毁 Activity,例如通过调用
finish()
或通过系统 BACK 导航。在这些情况下,您就会泄漏内存。此外,您可以创建 2 个以上 MainActivity
实例,在这种情况下,这些属性将仅指向最近实例化的 MainActivity
,这可能会导致问题。
你的很多麻烦都集中在这个:
internal class ClientThread : Runnable {
ContextCompat.getMainExecutor(appContext).execute /* command = */ {
MainActivity.otv.setBackgroundColor(Color.RED)
MainActivity.osb.visibility = View.VISIBLE
}
}
我真诚地希望没有任何书籍或课程可以演示这种技术,因为它有几个问题:
otv
、osb
)在引用它们之前已被填充。对此没有任何保证。MainActivity
的正确实例。如果有 2 个以上 MainActivity
实例,则可能不正确。MainActivity
的未销毁实例。尽管很有可能,但无法保证这一点。