{"action":"created","issue":{"url":"https://api.github.com/repos/plattysoft/Leonids/issues/19","labels_url":"https://api.github.com/repos/plattysoft/Leonids/issues/19/labels{/name}","comments_url":"https://api.github.com/repos/plattysoft/Leonids/issues/19/comments","events_url":"https://api.github.com/repos/plattysoft/Leonids/issues/19/events","html_url":"https://github.com/plattysoft/Leonids/issues/19","id":70531906,"number":19,"title":"Crash in ParticleField.onDraw","user":{"login":"kibantony","id":8175821,"avatar_url":"https://avatars.githubusercontent.com/u/8175821?v=3","gravatar_id":"","url":"https://api.github.com/users/kibantony","html_url":"https://github.com/kibantony","followers_url":"https://api.github.com/users/kibantony/followers","following_url":"https://api.github.com/users/kibantony/following{/other_user}","gists_url":"https://api.github.com/users/kibantony/gists{/gist_id}","starred_url":"https://api.github.com/users/kibantony/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kibantony/subscriptions","organizations_url":"https://api.github.com/users/kibantony/orgs","repos_url":"https://api.github.com/users/kibantony/repos","events_url":"https://api.github.com/users/kibantony/events{/privacy}","received_events_url":"https://api.github.com/users/kibantony/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":2,"created_at":"2015-04-23T22:47:31Z","updated_at":"2015-04-24T17:13:38Z","closed_at":null,"body":"There is a concurrency problem that is causing constant repeatable crashes. I've traced the issue to the fact that ParticleSystem.onUpdate is called via a Timer on a non-UI thread where it changes the contents of the mActiveParticles array. Meanwhile, the ParticleField view is accessing the same array to draw the particles on the UI thread, leading to the crash. A quick fix would be synchronize on the array to alleviate the contention, or use a Handler or similar mechanism to schedule the onUpdate operation on the UI thread.\r\n\r\n```\r\njava.lang.IndexOutOfBoundsException: Invalid index 50, size is 50\r\n        at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)\r\n        at java.util.ArrayList.get(ArrayList.java:308)\r\n        at com.plattysoft.leonids.ParticleField.onDraw(ParticleField.java:36)\r\n        at android.view.View.draw(View.java:14692)\r\n        at android.view.View.getDisplayList(View.java:13573)\r\n        at android.view.View.getDisplayList(View.java:13627)\r\n        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3095)\r\n        at android.view.View.getDisplayList(View.java:13498)\r\n        at android.view.View.getDisplayList(View.java:13627)\r\n        at android.view.View.draw(View.java:14409)\r\n        at android.view.ViewGroup.drawChild(ViewGroup.java:3121)\r\n        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2947)\r\n        at android.view.View.draw(View.java:14695)\r\n        at android.widget.FrameLayout.draw(FrameLayout.java:472)\r\n        at android.view.View.getDisplayList(View.java:13573)\r\n        at android.view.View.getDisplayList(View.java:13627)\r\n        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3095)\r\n        at android.view.View.getDisplayList(View.java:13498)\r\n        at android.view.View.getDisplayList(View.java:13627)\r\n        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3095)\r\n        at android.view.View.getDisplayList(View.java:13498)\r\n        at android.view.View.getDisplayList(View.java:13627)\r\n        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3095)\r\n        at android.view.View.getDisplayList(View.java:13498)\r\n        at android.view.View.getDisplayList(View.java:13627)\r\n        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3095)\r\n        at android.view.View.getDisplayList(View.java:13498)\r\n        at android.view.View.getDisplayList(View.java:13627)\r\n        at android.view.HardwareRenderer$GlRenderer.buildDisplayList(HardwareRenderer.java:1773)\r\n        at android.view.HardwareRenderer$GlRenderer.draw(HardwareRenderer.java:1638)\r\n        at android.view.ViewRootImpl.draw(ViewRootImpl.java:2624)\r\n        at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2469)\r\n        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2035)\r\n        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1095)\r\n        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6010)\r\n        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:799)\r\n        at android.view.Choreographer.doCallbacks(Choreographer.java:599)\r\n        at android.view.Choreographer.doFrame(Choreographer.java:559)\r\n        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:784)\r\n        at android.os.Handler.handleCallback(Handler.java:733)\r\n        at android.os.Handler.dispatchMessage(Handler.java:95)\r\n        at android.os.Looper.loop(Looper.java:157)\r\n        at android.app.ActivityThread.main(ActivityThread.java:5872)\r\n        at java.lang.reflect.Method.invokeNative(Native Method)\r\n        at java.lang.reflect.Method.invoke(Method.java:515)\r\n        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:852)\r\n        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:668)\r\n        at dalvik.system.NativeStart.main(Native Method)\r\n```"},"comment":{"url":"https://api.github.com/repos/plattysoft/Leonids/issues/comments/95995775","html_url":"https://github.com/plattysoft/Leonids/issues/19#issuecomment-95995775","issue_url":"https://api.github.com/repos/plattysoft/Leonids/issues/19","id":95995775,"user":{"login":"kibantony","id":8175821,"avatar_url":"https://avatars.githubusercontent.com/u/8175821?v=3","gravatar_id":"","url":"https://api.github.com/users/kibantony","html_url":"https://github.com/kibantony","followers_url":"https://api.github.com/users/kibantony/followers","following_url":"https://api.github.com/users/kibantony/following{/other_user}","gists_url":"https://api.github.com/users/kibantony/gists{/gist_id}","starred_url":"https://api.github.com/users/kibantony/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kibantony/subscriptions","organizations_url":"https://api.github.com/users/kibantony/orgs","repos_url":"https://api.github.com/users/kibantony/repos","events_url":"https://api.github.com/users/kibantony/events{/privacy}","received_events_url":"https://api.github.com/users/kibantony/received_events","type":"User","site_admin":false},"created_at":"2015-04-24T17:13:38Z","updated_at":"2015-04-24T17:13:38Z","body":"No problem. It's a great library and really saved me some time apart from this small issue. My test device is running 4.4.2. I'm creating the ParticleSystem like so...\r\n\r\n```\r\nmParticles = new ParticleSystem((Activity)getContext(), 100, R.drawable.particle, 5000)\r\n    .setSpeedRange(0.0f, 0.1f)\r\n    .setScaleRange(0.1f, 0.9f)\r\n    .setFadeOut(1000)\r\n    .setParentViewGroup((ViewGroup) findViewById(R.id.particle_view));\r\nmParticles.emit(0, 0, 10);\r\n```\r\n\r\nIn my parent view's onSizeChanged function I do the following to ensure the particles emit from the center on the view...\r\n```\r\n@Override\r\nprotected void onSizeChanged(int w, int h, int oldw, int oldh) {\r\n    super.onSizeChanged(w, h, oldw, oldh);\r\n    mParticles.updateEmitPoint(w / 2, h / 2);\r\n}\r\n```\r\n\r\nI'm also running some other animations within the parent view which cause frequent invalidates. All I have to do to see the crash is sit and let it run. Sometimes it happens immediately, sometimes it takes a couple minutes. It seems to happen a bit faster if I change the orientation (landscape<>portrait) of the device a few times to cause the view to resize & invalidate.\r\n\r\nI quickly worked around it by adding a synchronized(mActiveParticles) {} block in ParticleSystem.onUpdate, and a synchronized (mParticles) {} in ParticleField.onDraw. No more crashes."}}