简体   繁体   中英

Attempt to invoke on a null object while destructuring in a for loop

How is this even possible?

On a background thread, I'm running some computation that populates a list, then invalidates a view, and the view runs onDraw.

var list = mutableListOf<Pair<DataPoint, String>>()

...

generateBgData() {
    list.clear()
    list.add(...,...)
    invalidate()
}

In onDraw, I make a copy of the list, so as to prevent updates to the list from causing errors,

    val listCopy = ArrayList(list)
    for ((point, str)in listCopy) { // Null exception thrown here
        canvas.drawText(...)
    }

But on the line noted, I'm getting a null object reference error while destructuring java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object kotlin.Pair.component1()' on a null object reference . How is this even possible? My list is non-null, and nowhere do I ever set the list to null. If it is empty, the for loop should never run. I recreated the code running the issue here , and can't replicate it, but it happens very infrequently in my app on the play store.

Any idea what could possibly be happening?

The multi-threading is probably the culprit. Imagine your list has some items in it when this code runs:

val listCopy = ArrayList(list)

While the ArrayList constructor is copying items out of the list, the other thread clears the list, which marks everything null. If the other thread is faster at clearing the list than this thread is at copying the references over, it will start copying null references over for the last items in the list.

I recommend exclusively using read-only lists if you are modifying the data from multiple threads.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM