2

Grettiings, I'd asked this before, but even after the changes I'm still getting Concurrent Modification Exception, I'd implemented synchronizedList and synchronized(list) but the exception is still happening, I running out of ideas, could you give some advice what could still be happening? Thanks

manager.getMutableList()
        .observe(viewLifecycleOwner, Observer { queueList ->
            Collections.synchronizedList(ArrayList<Object>()).apply {
                this.addAll(queueList)
                synchronized(this) {
                    if (this.isNotEmpty()) {
                        // Do Something
                    } else {
                        // Do other stuff
                    }

                    (recyclerView.adapter as Adapter).run {
                        items = this@apply
                        notifyDataSetChanged()
                        hideLoadingScreen()
                    }
                }
            }
        })

This is the trace of the exception

Fatal Exception: java.util.ConcurrentModificationException
   at java.util.ArrayList$SubList.size(ArrayList.java:1057)
   at java.util.AbstractCollection.toArray(AbstractCollection.java:136)
   at java.util.ArrayList.addAll(ArrayList.java:588)
   at java.util.Collections$SynchronizedCollection.addAll(Collections.java:2089)
   at com.sample.app.ui.Fragment$setObservers$6.onChanged(Fragment.java:382)
   at com.sample.app.ui.Fragment$setObservers$6.onChanged(Fragment.java:89)
   at androidx.lifecycle.LiveData.considerNotify(LiveData.java:131)
   at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:144)
   at androidx.lifecycle.LiveData$ObserverWrapper.activeStateChanged(LiveData.java:443)
   at androidx.lifecycle.LiveData$LifecycleBoundObserver.onStateChanged(LiveData.java:395)
   at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:361)
   at androidx.lifecycle.LifecycleRegistry.forwardPass(LifecycleRegistry.java:300)
   at androidx.lifecycle.LifecycleRegistry.sync(LifecycleRegistry.java:339)
   at androidx.lifecycle.LifecycleRegistry.moveToState(LifecycleRegistry.java:145)
   at androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent(LifecycleRegistry.java:131)
   at androidx.fragment.app.FragmentViewLifecycleOwner.handleLifecycleEvent(FragmentViewLifecycleOwner.java:51)
   at androidx.fragment.app.Fragment.performStart(Fragment.java:2737)
   at androidx.fragment.app.FragmentStateManager.start(FragmentStateManager.java:365)
   at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1194)
   at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1356)
   at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1434)
   at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:442)
   at androidx.fragment.app.FragmentManager.executeOps(FragmentManager.java:2169)
   at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1992)
   at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1947)
   at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1849)
   at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2629)
   at androidx.fragment.app.FragmentManager.dispatchStart(FragmentManager.java:2583)
   at androidx.fragment.app.Fragment.performStart(Fragment.java:2739)
   at androidx.fragment.app.FragmentStateManager.start(FragmentStateManager.java:365)
   at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1194)
   at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1356)
   at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1434)
   at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1497)
   at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2625)
   at androidx.fragment.app.FragmentManager.dispatchStart(FragmentManager.java:2583)
   at androidx.fragment.app.Fragment.performStart(Fragment.java:2739)
   at androidx.fragment.app.FragmentStateManager.start(FragmentStateManager.java:365)
   at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1194)
   at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1356)
   at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1434)
   at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1497)
   at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2625)
   at androidx.fragment.app.FragmentManager.dispatchStart(FragmentManager.java:2583)
   at androidx.fragment.app.FragmentController.dispatchStart(FragmentController.java:258)
   at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:550)
   at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:210)
   at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1419)
   at android.app.Activity.performStart(Activity.java:7479)
   at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3454)
   at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:180)
   at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:165)
   at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:142)
   at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2199)
   at android.os.Handler.dispatchMessage(Handler.java:112)
   at android.os.Looper.loop(Looper.java:216)
   at android.app.ActivityThread.main(ActivityThread.java:7625)
   at java.lang.reflect.Method.invoke(Method.java)
   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)
  • at com.sample.app.ui.Fragment$setObservers$6.onChanged(Fragment.java:382) at com.sample.app.ui.Fragment$setObservers$6.onChanged(Fragment.java:89) what's on these lines? – IR42 Aug 12 '20 at 07:30
  • The 382 line is **this.addAll(queueList)** of the code section, the 89 line is where the Fragment class begings **class Fragment: Fragment() {** – Jose Grillo Aug 12 '20 at 07:35
  • i suspect you are modifying original `queueList` from different thread (in your `manager`) – IR42 Aug 12 '20 at 08:28

1 Answers1

0

It looks to me like you are locking on "this", which is a list unique to each execution. You should lock on an object that is shared, like for instance the queueList.

  • But if I'm checking the isEmpty condition over the synchronizedList, that represent the this in lockable, why should I lock the original list that I've initially cloned? – Jose Grillo Aug 12 '20 at 07:24
  • I was reading to may use CopyOnWriteArrayList instead of Collections.synchronizedList, and remove the lock of the list – Jose Grillo Aug 12 '20 at 07:28
  • Each thread that comes in here creates a copy of the mutable list. You are locking on that copy, but since each thread has its own copy you are never blocking anything. The syncronize has no effect. If you lock on the queueList then no two threads can ever reach "Do Something" at the same time. – alex-jesper Aug 12 '20 at 08:07