Anyone have any solution to resolve concurrency is...
# android
s
Anyone have any solution to resolve concurrency issue on ArrayList? Firebase crash log:
Copy code
Fatal Exception: java.util.ConcurrentModificationException
       at java.util.ArrayList$Itr.next(ArrayList.java:860)
My code:
Copy 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
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
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
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
Many thanks @gildor @Arun. I got it.
g
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
Epoxy will do a diff on the list. So you shouldn't have any visible issues while updating the list.
s
Hello everyone, I have used CopyOnWriteArrayList but not working Fatal Exception: java.util.ConcurrentModificationException
Copy code
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
Yes, both, because both are not thread safe
Thread safety already broken here:
Copy code
CopyOnWriteArrayList<Conversation>(dataConversation)
Ands I really not sure why you need cloneListConcurrency
s
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
it not remove item while delete out of list
What do you mean?
s
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
127 Views