0

I have a class that calls on another class to create an object - essentially a factory worker. The addTest function in the TestRepository returns this created object back to the TestUnit class when addTest is called. The TestUnit class does not keep any references to the object, so I would expect that when the TestUnit class is no longer used, it gets garbage collected. However in this example, even though no reference is maintained, the object being returned to the TestUnit class does have a field that contains a reference to a lambda (the setTestToRunSync function). Because this lambda is defined in the TestUnit class, I suspect that the TestUnit class treats this as some kind of reference and even though you can set the instance of TestUnit to null, the TestInfo object still maintains a reference to the TestUnit class, preventing it from ever being garbage collected. Is this true? I don't see any easy way of telling in Android Studio if a class is still resident in memory. My goal is to store instances of TestInfo in the TestRepository and then be certain that the TestUnit class is destroyed after its done storing the TestInfo object.

Here's the sample code:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        setSupportActionBar(toolbar)

        var testUnit: TestUnit? = TestUnit()
        testUnit = null
    }
}

class TestUnit : TestSetup() {
    init {
        addTest("Add Numbers").setTestToRunSync {
            // Does creating this lambda function
            // keep the TestUnit class resident in memory?
            var x = 0
            x++
        }
    }
}

object TestRepository {
    val tests: MutableList<TestInfo> = mutableListOf()

    fun addTest(testName: String): TestInfo {
        val test = TestInfo(testName)
        tests.add(test)
        return test
    }

    fun getAllTests(): MutableList<TestInfo> {
        return tests
    }
}

open class TestSetup {
    fun addTest(testName: String): TestInfo {
        return TestRepository.addTest(testName)
    }
}

class TestInfo(private val name: String) {
    var testName: String = name

    private var testToRunSync: (suspend () -> Unit)? = null

    fun setTestToRunSync(testToRun: suspend () -> Unit): TestInfo {
        this.testToRunSync = testToRun
        return this
    }
}
Johann
  • 27,536
  • 39
  • 165
  • 279
  • What is `TestSetup`? What is `setTestToRunSync`? How does `TestUnit` manage to call `addTest` defined in `TestRepository`? Or, is this a different method? – Steven Jeuris Dec 12 '19 at 14:10
  • I think the answer to this question involves potential memory leaks when using closures. Here is a Kotlin specific question on this topic (at a glance): https://stackoverflow.com/q/42271208/590790 – Steven Jeuris Dec 12 '19 at 14:16

0 Answers0