https://kotlinlang.org logo
Title
s

Sam

05/20/2020, 4:13 AM
Anyone have any solution to resolve concurrency issue on ArrayList? Firebase crash log:
Fatal Exception: java.util.ConcurrentModificationException
       at java.util.ArrayList$Itr.next(ArrayList.java:860)
My code:
val dataConversation = ArrayList<Conversation>() // global

// in background ( I have use Epoxy - Airbnb )
val cloneListConcurrency = arrayListOf<Conversation>().apply { addAll(dataConversation) }
        with(cloneListConcurrency.iterator()) {
            forEach {
// do something to display 
}}

// in background
fun deleteConversation(conversationId: String?) {
        for (index in 0 until dataConversation.size) {
            val item = dataConversation[index]
            if (item.id == conversationId) {
                dataConversation.removeAt(index)
                break
            }
        }
    }
Many Thanks.
a

Arun

05/20/2020, 4:17 AM
An easy fix is to use
CopyOnWriteArrayList
which is thread safe. However a proper fix for this is to use immutable lists and publish new list to epoxy on changes. Epoxy internally does diffing to find the changed items. In this case, if you want to delete an item, delete it outside of epoxy and pass a new list to epoxy. Epoxy will take care of rendering it.
❤️ 2
2
s

Sam

05/20/2020, 4:22 AM
1. Do you know why the problem still happen on it on cloneListConcurrency ? I delete on dataConversation and render on cloneListConcurrency. 2. But I think it will be heavy on memory , Do you have any blink/flash on screen after passing a new list ? My app is supporting the low-end devices.
g

gildor

05/20/2020, 4:24 AM
2. It shouldn’t be any memory issues on practice, copy is very fast for not very big lists (like below 1000). If it blinks, it probably re-render too much data. I’m not familiar with Epoxy, but this problem of rendering not memory
1. It still a problem because addAll is non-atomic, it creates iterator under the hood and iterate on list to get all elements, so if list will be changed during this iteration, it will fail with ConcurrentModificationException
❤️ 1
1
protect access to dataConversation, use CopyOnWriteArrayList as Arunkumar suggested or use something like mutex
s

Sam

05/20/2020, 4:29 AM
Many thanks @gildor @Arun. I got it.
g

gildor

05/20/2020, 4:30 AM
but use immutable list is still better idea imo, even if you increase a bit GC pressure, probably it’s not an issue anyway itself, you have much more objects created and rendered during re-rendering of the screen and if you do not do this every frame it will impossible to notice on practice
🎉 1
s

Subhrajyoti Sen

05/20/2020, 9:08 AM
Epoxy will do a diff on the list. So you shouldn't have any visible issues while updating the list.
s

Sam

05/22/2020, 2:05 AM
Hello everyone, I have used CopyOnWriteArrayList but not working Fatal Exception: java.util.ConcurrentModificationException
val cloneListConcurrency = CopyOnWriteArrayList<Conversation>(dataConversation)
        with(cloneListConcurrency.iterator()) {
//todo something
}

/// modify outside with (CRUD
 dataConversation
And I have one crash Fatal Exception: java.lang.NegativeArraySizeException -1 => so how can I resolve two issues? Thanks….
or I should change dataConversation from ArrayList to CopyOnWriteArrayList ?
g

gildor

05/22/2020, 2:30 AM
Yes, both, because both are not thread safe
Thread safety already broken here:
CopyOnWriteArrayList<Conversation>(dataConversation)
Ands I really not sure why you need cloneListConcurrency
s

Sam

05/22/2020, 2:32 AM
only for make sure it not remove item while delete out of list. But I think its not working for now. I will change dataConversation (Arraylist) to CopyOnWriteArrayList and remove cloneListConcurrency. THanks @gildor
g

gildor

05/22/2020, 2:45 AM
it not remove item while delete out of list
What do you mean?
s

Sam

05/22/2020, 3:35 AM
I mean Im using socket.io to sending an event to automate delete item on dataConversation (List) so last release I have used cloneListConcurrency (CopyOnWriteArrayList) for make sure it doesn’t crash, But still have problem. => so I will change dataConversation(ArrayList) to CopyOnWriteArrayList. Thanks @gildor