androidkotlinandroid-application-class

Object not being added to ArrayList inside a Thread of Application class


I'm working with Kotlin in Android app development.

This is the code I'm trying to run when the Application is instantiated

class SpeechApp: Application() {
    var isDictionaryRead = false
    lateinit var wordslist : ArrayList<String>

    override fun onCreate() {
        super.onCreate()
        wordslist = ArrayList()

        Thread {
            Runnable {
                execute()
            }
        }.start()
    }

    fun execute() {
        val inputStream = assets.open("words.txt")
        val reader = BufferedReader(InputStreamReader(inputStream))

        var line = reader.readLine()
        while (line != null) {
            Log.i("Read" , line)
            wordslist.add(line)
            line = reader.readLine()
        }
        isDictionaryRead = true
    }
}

I'm expecting this code to work, but in my logs I cannot see any line being added that has the tag Read. But if I call the execute() outside the Thread like:

class SpeechApp: Application() {
    var isDictionaryRead = false
    lateinit var wordslist : ArrayList<String>

    override fun onCreate() {
        super.onCreate()
        wordslist = ArrayList()

        execute()
    }

    fun execute() {
        val inputStream = assets.open("words.txt")
        val reader = BufferedReader(InputStreamReader(inputStream))

        var line = reader.readLine()
        while (line != null) {
            Log.i("Read" , line)
            wordslist.add(line)
            line = reader.readLine()
        }
        isDictionaryRead = true
    }
}

I can see a lot of lines in my logcat with the "Read" tag. I do not want it to work this way, as there is a visible lag of ~5s before I see my MainActivity, as the system is busy processing the 479k words inside words.txt.

How can I make execute() work inside the thread?


Solution

  • The Runnable is actually never run. Instead run it manually or use the proper constructors:

    Thread { execute() }.start()
    
    Thread(::execute).start()
    
    Thread(Runnable {
        execute()
    }).start()
    
    Thread {
        Runnable {
            execute()
        }.run()
    }.start()
    

    The reason for your issue is more visible when not using SAM conversion for the constructor:

    Thread(object : Runnable {
        override fun run() {
            Runnable {
                execute()
            }
        }
    }).start()