Giter Club home page Giter Club logo

Comments (35)

ericpanorel avatar ericpanorel commented on May 17, 2024

OK, so I ended up not doing this. Instead, I overrode the method onBeforeClusterRendered to give a clue to the user, that in that cluster, there's something going on.

The problem with my logic above, is that when it's zoomed out, no clusters will be rendered, and all icons will be drawn (mine has about 200)

But still, just in case you have a use-case for this scenario...

from android-maps-utils.

broady avatar broady commented on May 17, 2024

Thanks for the report! Is this easy to reproduce?

This is a bit odd – I wonder why removeAll() gets called. Perhaps we need to take a copy of the cluster set at the beginning of rendering.

from android-maps-utils.

ericpanorel avatar ericpanorel commented on May 17, 2024

In my case, I find that it can be reproduce, if you override the method shouldRenderAsCluster and return false all the time

from android-maps-utils.

 avatar commented on May 17, 2024

I get the same issue but I can't say why I get it and can't reproduce it

java.util.ConcurrentModificationException
        at java.util.HashMap$HashIterator.nextEntry(HashMap.java:806)
        at java.util.HashMap$KeyIterator.next(HashMap.java:833)
        at java.util.AbstractSet.removeAll(AbstractSet.java:110)
        at com.google.maps.android.clustering.view.DefaultClusterRenderer$RenderTask.run(DefaultClusterRenderer.java:382)
        at java.lang.Thread.run(Thread.java:841)

Actually, I'm quite surprised to see only two people here that have encountered this issue, it happens quite often when you play to zoom/un-zoom on a map with Clusters.

from android-maps-utils.

newmanw avatar newmanw commented on May 17, 2024

Yeah I am seeing this as well. I thought it was something I was doing but that was not the case. An progress or updates? I wrote #74 before I realized there was already an open ticket.

from android-maps-utils.

broady avatar broady commented on May 17, 2024
 1.) Not that it matters, - my marker locations are trickling in (coming from a network call)

I think this does actually matter, and is likely what triggers this bug. I'll investigate.

from android-maps-utils.

rudmac avatar rudmac commented on May 17, 2024

I also have encountered the same issue, I got an ACRA error log report from one of my app.

java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:806)
at java.util.HashMap$KeyIterator.next(HashMap.java:833)
at java.util.AbstractSet.removeAll(AbstractSet.java:110)
at com.google.maps.android.a.b.l.run(DefaultClusterRenderer.java:383)
at java.lang.Thread.run(Thread.java:841)

from android-maps-utils.

rgeldmacher avatar rgeldmacher commented on May 17, 2024

I also got the same error and have debugged the issue a bit more.
What happens is that the RenderTask calls the method markerModifier.waitUntilFree(); before it removes all new markers from the markersToRemove Set. Unfortunately the waitUntilFree method returns too early and the newMarkers Set is modified while being used in the removeAll method.

waitUntilFree returns too early, because the isBusy() method in the MarkerModifier will return false as soon as it's Queues are empty, i.e. when the last modifier task has been started. The task however is still running and in the case of the CreateMarkerTasks will modify the newMarker Set of the RenderTask.

=> MarkerModifier.isBusy() should return false only after all it's task have been finished

I used an ugly workaround in the closed source project I'm currently working on, which uses a counter and a callback for the CreateMarkerTasks to fix the isBusy method. Not pretty and I currently don't have time to provide a proper fix for this, but I hope my analysis helps a bit.

from android-maps-utils.

JonasDaWi avatar JonasDaWi commented on May 17, 2024

I have the same issue. I also get the markers from a network call. I'm writing this because i'd like to launch my app soon and with this bug it's impossible to publish the app ;-)

from android-maps-utils.

newmanw avatar newmanw commented on May 17, 2024

Agreed, marker cluster is 100% unusable until this is fixed.

from android-maps-utils.

spyd3r avatar spyd3r commented on May 17, 2024

I also am experiencing this issue. I hadn't seen the issue in my testing phase, and just launched my app last night. First time I used it today, this issue occurred.

from android-maps-utils.

mypplication avatar mypplication commented on May 17, 2024

I have add "synchronized" to the run method in RenderTask class. No problem since.

public synchronized void run()

from android-maps-utils.

broady avatar broady commented on May 17, 2024

Interesting. If that actually fixes it, then there's a bug somewhere else, since only one RenderTask should be running at a time.

from android-maps-utils.

dlukashev avatar dlukashev commented on May 17, 2024

got the same issue today
java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:806)
at java.util.HashMap$KeyIterator.next(HashMap.java:833)
at java.util.AbstractSet.removeAll(AbstractSet.java:110)
at com.google.maps.android.clustering.view.DefaultClusterRenderer$RenderTask.run(DefaultClusterRenderer.java:383)
at java.lang.Thread.run(Thread.java:841)

from android-maps-utils.

sinisakendel avatar sinisakendel commented on May 17, 2024

The same issue - it happens more often when I don't have any clusters, just plain markers. "synchronized" in RenderTask didn't fix it.

from android-maps-utils.

ento avatar ento commented on May 17, 2024

I believe I'm against the same problem, although it's manifesting in a different way: markers sometimes disappear after zooming in, out and in again. After investigating the code, I came to the same conclusion as rgeldmacher: isBusy() is not reporting the full truth. Here's a prettified debug log:

05-26 21:11:40.239 MyRenderer.onClustersChanged     onClustersChanged: size 1
05-26 21:11:40.239 MarkerModifier.performNextTask   perform mOnScreenCreateMarkerTasks
05-26 21:11:40.269 MarkerModifier.waitUntilFree     finished waiting until free
05-26 21:11:40.269 RenderTask.run                   markersToRemove: size 2, newMarkers: size 0, CreateMarkerTasks: added 1
05-26 21:11:40.269 RenderTask.run                   - marker to remove: 1140931912
05-26 21:11:40.269 RenderTask.run                   - marker to remove: 1143961664
05-26 21:11:40.389 MyRenderer.onClusterItemRendered rendering marker: 1143961664
05-26 21:11:40.389 CreateMarkerTask.perform         add item to newMarkers: 1143961664
05-26 21:11:40.389 MarkerModifier.waitUntilFree     is busy, waiting...
05-26 21:11:40.389 MarkerModifier.performNextTask   perform mOnScreenRemoveMarkerTasks
05-26 21:11:40.389 MyMarkerManager                  remove marker: 1143961664
05-26 21:11:40.389 MarkerModifier.performNextTask   perform mRemoveMarkerTasks
05-26 21:11:40.399 MyMarkerManager                  remove marker: 1140931912
05-26 21:11:40.399 MarkerModifier.waitUntilFree     finished waiting until free

As a workaround, I've copied the entire DefaultClusterRenderer.java into my project, changed the package, and modified MarkerModifier.performNextTask to remove the task from the queue only after performing it.

        private void performNextTask() {
            if (!mOnScreenRemoveMarkerTasks.isEmpty()) {
                removeMarker(mOnScreenRemoveMarkerTasks.peek());
                mOnScreenRemoveMarkerTasks.remove();
            } else if (!mAnimationTasks.isEmpty()) {
                mAnimationTasks.peek().perform();
                mAnimationTasks.remove();
            } else if (!mOnScreenCreateMarkerTasks.isEmpty()) {
                mOnScreenCreateMarkerTasks.peek().perform(this);
                mOnScreenCreateMarkerTasks.remove();
            } else if (!mCreateMarkerTasks.isEmpty()) {
                mCreateMarkerTasks.peek().perform(this);
                mCreateMarkerTasks.remove();
            } else if (!mRemoveMarkerTasks.isEmpty()) {
                removeMarker(mRemoveMarkerTasks.peek());
                mRemoveMarkerTasks.remove();
            }
        }

I'm not sure this is the right and cleanest fix, but the symptom seems to have gone away.

from android-maps-utils.

ianschmitz avatar ianschmitz commented on May 17, 2024

Had the same issue today. Still no fix for this?

from android-maps-utils.

tealsoftware avatar tealsoftware commented on May 17, 2024

Getting

06-10 21:18:08.644  28224-28549/myapp.app E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-4561
java.util.ConcurrentModificationException
        at java.util.HashMap$HashIterator.nextEntry(HashMap.java:792)
        at java.util.HashMap$KeyIterator.next(HashMap.java:819)
        at java.util.AbstractSet.removeAll(AbstractSet.java:110)
        at myapp.CustomClusterRenderer$RenderTask.run(CustomClusterRenderer.java:387)
        at java.lang.Thread.run(Thread.java:856)

My CustomClusterRenderer isn't that custom BTW.

from android-maps-utils.

GMc14 avatar GMc14 commented on May 17, 2024

Update regarding disappearing markers:
When the the markers disappear, "onClusterItemRendered" is called in the ClusterRenderer as usual, and the marker is non-null. But when I zoom in/out to cause it to reappear (actually render), the marker is now null and hits onBeforeClusterItemRendered first.

from android-maps-utils.

pbertsch avatar pbertsch commented on May 17, 2024

Got the same error a few minutes ago. I actually never got it before.
I was asking myself if its not possible using a ConcurrentSkipListSet, that could solve the problem and because the basic operations in O(log n). So if the Cluster is not too big you should be fine. What do you all think about that ?

from android-maps-utils.

sjr avatar sjr commented on May 17, 2024

We are getting a few of these too, a fix would be great.

from android-maps-utils.

OlekBodashko avatar OlekBodashko commented on May 17, 2024

I have the same issue:

FATAL EXCEPTION: Thread-4737
Process: pt.inm.prd.android.twork, PID: 11369
java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:806)
at java.util.HashMap$KeyIterator.next(HashMap.java:833)
at java.util.AbstractSet.removeAll(AbstractSet.java:110)
at com.google.maps.android.clustering.view.DefaultClusterRenderer$RenderTask.run(DefaultClusterRenderer.java:384)
at java.lang.Thread.run(Thread.java:841)

When is called:

 markersToRemove.removeAll(newMarkers);

from android-maps-utils.

elisealix22 avatar elisealix22 commented on May 17, 2024

FWIW I'm consistently seeing the same thing when I return false in shouldRenderAsCluster and then zoom out the map

java.util.ConcurrentModificationException
            at java.util.HashMap$HashIterator.nextEntry(HashMap.java:806)
            at java.util.HashMap$KeyIterator.next(HashMap.java:833)
            at java.util.AbstractSet.removeAll(AbstractSet.java:110)
            at com.google.maps.android.clustering.view.DefaultClusterRenderer$RenderTask.run(DefaultClusterRenderer.java:383)
            at java.lang.Thread.run(Thread.java:841)

from android-maps-utils.

C0nstan avatar C0nstan commented on May 17, 2024

Same issue here!

from android-maps-utils.

yrulee avatar yrulee commented on May 17, 2024

I think ento and rgeldmacher have found the root cause : Each task in queue should be performed completely before being removed from queue.

The queue.poll().perform() should be fixed.

from android-maps-utils.

czechnology avatar czechnology commented on May 17, 2024

Same here. Never got this bug before but now during final testing I get it when playing around with the map, where there are no clusters at all, just normal markers.

W/dalvikvm( 2288): threadid=44: thread exiting with uncaught exception (group=0x41d9c700)
E/AndroidRuntime( 2288): FATAL EXCEPTION: Thread-20951
E/AndroidRuntime( 2288): java.util.ConcurrentModificationException
E/AndroidRuntime( 2288):        at java.util.HashMap$HashIterator.nextEntry(HashMap.java:806)
E/AndroidRuntime( 2288):        at java.util.HashMap$KeyIterator.next(HashMap.java:833)
E/AndroidRuntime( 2288):        at java.util.AbstractSet.removeAll(AbstractSet.java:110)
E/AndroidRuntime( 2288):        at com.google.maps.android.a.b.b$f.run(DefaultClusterRenderer.java:384)
E/AndroidRuntime( 2288):        at java.lang.Thread.run(Thread.java:841)

Not easy to recreate this bug though.

from android-maps-utils.

dimomite avatar dimomite commented on May 17, 2024

I've found potential problem in the code:
Method com.google.maps.android.clustering.view.DefaultClusterRenderer.MarkerModifier.isBusy() works with protected data queues, like mCreateMarkerTasks, mOnScreenCreateMarkerTasks, ... It's called 3 times, and 2 of them are protected with lock, however here:

        public void waitUntilFree() {
            while (isBusy()) {

lock is not used. And waitUntilFree() is also called without locking. So I'd recommend to wrap return with the lock:

        public boolean isBusy() {
            lock.lock();
            try {
                return ...;
            } finally {
                lock.unlock();
            }
        }

As far as i understood everybody have crashes in line markersToRemove.removeAll(newMarkers); If RenderTask.run() can run only in a one thread at the same time, then markersToRemove (and member mMarkers that holds reference on the same set-object at that moment of time) is saved from threading issues.
However local Set<MarkerWithPosition> newMarkers can cause problems. It is shared with CreateMarkerTask instances and is modified inside its perform() method while called from UI thread on each MarkerModifier.handleMessage() call.

In this conditions we can get ConcurrentModificationException in this case:

  • markerModifier.waitUntilFree(); returns control to RenderTask's thread too early due to not thread save implementation of MarkerModifier.isBusy()
  • RenderTask's thread starts execution of markersToRemove.removeAll(newMarkers);
  • VirtualMashine switches control to UI thread
  • MarkerModifier.handleMessage() is invoked and tries to modify shared set newMarkers in CreateMarkerTask.perform()

Summary. Those who had issues, try to add lock to isBusy() and check.

from android-maps-utils.

pytel87 avatar pytel87 commented on May 17, 2024

Same issue: ConcurrentModificationException when removeAll() called

from android-maps-utils.

francos avatar francos commented on May 17, 2024

Hi,

I'm having this same issue when just zooming out fast in the map when there are a lot of clusters/markers visible.

09-03 12:04:15.425    6231-8568/co.vmob.outofthebox W/dalvikvm﹕ threadid=30: thread exiting with uncaught exception (group=0x4157bba8)
09-03 12:04:15.425    6231-8568/co.vmob.outofthebox E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-22949
    Process: co.vmob.outofthebox, PID: 6231
    java.util.ConcurrentModificationException
            at java.util.HashMap$HashIterator.nextEntry(HashMap.java:806)
            at java.util.HashMap$KeyIterator.next(HashMap.java:833)
            at java.util.AbstractSet.removeAll(AbstractSet.java:110)
            at com.google.maps.android.clustering.view.DefaultClusterRenderer$RenderTask.run(DefaultClusterRenderer.java:383)
            at java.lang.Thread.run(Thread.java:841)

I'm using a custom cluster renderer that only adds titles to the clusters and markers (and a custom icon to the markers as well):

private Context mContext;

public VenuesClusterRenderer(Context context, GoogleMap map, ClusterManager<VenueClusterItem> clusterManager) {
    super(context, map, clusterManager);

    mContext = context;
}

@Override
protected void onBeforeClusterRendered(Cluster<VenueClusterItem> cluster, MarkerOptions markerOptions) {
    super.onBeforeClusterRendered(cluster, markerOptions);

    // Add title to the cluster indicating exactly how many venues are inside it
    markerOptions.title(mContext.getString(R.string.venues_cluster_title, cluster.getSize()));
}

@Override
protected void onBeforeClusterItemRendered(VenueClusterItem item, MarkerOptions markerOptions) {
    super.onBeforeClusterItemRendered(item, markerOptions);

    // Add title to the venue indicating its address
    markerOptions.title(item.getVenue().getAddress());

    // Set a custom venue marker
    markerOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_map_marker));
}

from android-maps-utils.

Shailevy avatar Shailevy commented on May 17, 2024

I'm seeing the same issue reported many time my crash reporting service (BugSense)

I will try the isBusy() workaround suggested here and hope the problem will go ago until a proper fix comes out

Edit: Oh, wait, isBusy belongs to MarkerModifier which is an internal private class I can't override without modifying the library code. I'd rather not touch the library.

Any workarounds anyone can suggest ?

from android-maps-utils.

jlmcdonnell avatar jlmcdonnell commented on May 17, 2024

I'm guessing this still hasn't been fixed

from android-maps-utils.

broady avatar broady commented on May 17, 2024

@dimomite fantastic - that looks like the problem. would you send a pull request?

from android-maps-utils.

broady avatar broady commented on May 17, 2024

Released as 0.3.2 - can you all try this new version and see if you still see the problem?

from android-maps-utils.

kashoory avatar kashoory commented on May 17, 2024

It sounds like it has been fixed. Four phones ran my application for about 60 hours without exception which was impossible before this fix!

from android-maps-utils.

jilenloa avatar jilenloa commented on May 17, 2024

I think you are right @kashoory. I don't see that crash happening anymore.

from android-maps-utils.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.