因此,我对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正在拆除活动, 重新实例化它旋转,但我的同伴变量(otv和osb)在onCreate中更新! 这是否意味着旧的值失go 了引用计数并获得了GCed?

我承认我真的不知道我在做什么,我只是不停地try ,直到它奏效. 这个代码有多难闻?这款应用很时髦,效果也很好!

推荐答案

它似乎工作得很好,即使屏幕旋转也是如此

它有问题.

我真的是在泄露内存吗?

是的对于您问题中的文字代码,影响最小,但如果您打算更改该代码,影响可能会变得更糟.

当我旋转屏幕时,想必Android正在删除活动,并重新实例化它旋转,但我的同伴var(OTV和OSB)在onCreate中更新了!这是否意味着旧的价值失go 了裁判的数量并获得了GCed?

是.但是,请记住,除了配置更改之外,还有其他方式可以销毁活动,例如通过呼叫finish()或通过系统返回导航.在这些情况下,您正在泄漏内存.此外,您可以创建MainActivity的2个以上实例,在这种情况下,这些属性将只指向最近实例化的MainActivity,这可能会导致问题.


你的很多麻烦都围绕着这一点:

    internal class ClientThread : Runnable { 

        ContextCompat.getMainExecutor(appContext).execute /* command = */  {
            MainActivity.otv.setBackgroundColor(Color.RED)
            MainActivity.osb.visibility = View.VISIBLE
        }

    }

这有几个问题:

  1. 您假设这些属性(otvosb)在引用它们之前被填充.对此没有任何保证.
  2. 您假设这些属性指向MainActivity的正确实例.如果有2个以上的MainActivity个实例,则可能不正确.
  3. 您假设这些属性指向一个未销毁的MainActivity实例.这一点不能保证,尽管可能性很大.
  4. 这种编程方法是导致您首先创建那些可能泄漏的属性的原因.

Android相关问答推荐

在画布上画直线

编写视觉转型

无法列出目录中的文件'

如何在Android中使用TextView设置动态文本的样式

了解数据加载在Kotlin中的工作原理

Android Studio -未显示布局预览(不推荐使用安全管理器)

Android Compose Pages 3-一次加载所有页面,无需在LazyColumn中滚动,无需网络调用和内部滚动

从惰性列中删除项目时Jetpack Compose崩溃

Play Google上发布的一款应用的房间数据库迁移

插入视图模型时,dagger 未命中绑定错误

如何判断堆肥是否为空?

没有打开历史记录的活动意向 Select 器完成调用活动

Android Studio XML 文本在 ConstraintLayout 中不居中

用作输入参数的 Lambda 函数导致重组

如何使用 Glide 将图像下载到设备内部存储

Android Studio (Kotlin):无法启动活动

如何让用户与任意应用程序共享文件?

如何从构建的流对象中发出值

如何将私有 mutableStateOf 分配给 Android Jetpack 中的 State 变量?

Xamarin 获取动态 ListView DataTemplate 中的按钮单击事件数据