Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash on mDrawingView.postInvalidate(); (We have tens of millions of users) #85

Open
ynkm169 opened this issue Oct 3, 2017 · 9 comments

Comments

@ynkm169
Copy link

ynkm169 commented Oct 3, 2017

Stack trace:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.postInvalidate()' on a null object reference
com.plattysoft.leonids.ParticleSystem.onUpdate(ParticleSystem.java:683)
com.plattysoft.leonids.ParticleSystem.access$000(ParticleSystem.java:38)
access$100
com.plattysoft.leonids.ParticleSystem$ParticleTimerTask.run(ParticleSystem.java:82)
java.util.TimerThread.mainLoop(TimerThread.java:555)
java.util.TimerThread.run(TimerThread.java:505)

Hi,

We use this library to do some fancy particle effects for our app.
We received crash report on this line.
How could we possible fix this?
An obvious fix is to add if(mDrawingView != null), however, I am not sure what consequence this might cause.

Thanks
Yujiao

@plattysoft
Copy link
Owner

plattysoft commented Oct 3, 2017

That's strange because that view is created by the ParticleSystem and since it holds a reference to it, the object should not be deallocated.

The most logical explanation is that the ParticleSystem is still trying to render something when the views are deallocated (but it is usually destroyed within the Activity lifecycle),

I think the safest option is to explicitly call cancel() inside onDestroy() of your Activity / Fragment to make sure that everything stops nicely.

Let me know if this helps.

@plattysoft
Copy link
Owner

plattysoft commented Oct 3, 2017

OTOH, checking if the view is null before calling postInvalidate should be safe. If the view is null it is not going to draw anything. Also, in that case, it would make sense to call cancel. I may add that as a safety measure :)

@ynkm169
Copy link
Author

ynkm169 commented Oct 4, 2017

Hi plattysoft,

Thanks for helping!
Could you please add null check? We use gradle so we can't change this locally.

We call cancel() in a few places. It seems this in turn calls cleanupAnimation() which sets mDrawingView null.

We also sometimes call cancel() in a different thread by postDelayed.

Yujiao

@plattysoft
Copy link
Owner

Maybe that's the problem. Let me explain it:

cancel is designed to abruptly end the animation and stop everything, getting ready for garbage collection. You are not supposed to reuse a ParticleSystem after you call cancel, you are supposed to create a new one.

stopEmitting, on the other hand, stops emitting new particles, but the ones that exist do continue to animate. It is safe to call startEmitting again after stopEmitting.

To be fair, the ParticleSystem should throw an exception if startEmitting is called after cancel, that could be an interesting improvement.

Please let me know if this is your case.

@ynkm169
Copy link
Author

ynkm169 commented Oct 5, 2017

Hi plattysoft,

I will debug our app a bit more next week to reproduce the exact circumstance that caused crash and let you know what happened.

Thanks

@ynkm169
Copy link
Author

ynkm169 commented Oct 16, 2017

Hi plattysoft,

We end up using stopEmitting() only, and removed cancel().
The original code was calling both stopEmitting and cancel to completely stop the particleSystem.

We will monitor crash report for similar issues once our new app is released.

Thanks
Yujiao

@plattysoft
Copy link
Owner

Thanks for letting me know. I've been meaning to ask you about that for a couple of days.

I expect that crash to go away, or at least to decrease the prominence. Essentially if you reused a ParticleSystem after calling cancel, it would crash, so calling just stopEmitting should be safer.

Keep me updated either way.

@ynkm169
Copy link
Author

ynkm169 commented Oct 16, 2017

We use postDelay in UI thread. There is no synchronization issues.

@renyuzhuo
Copy link

renyuzhuo commented Nov 7, 2017

Yes, I get the same NullPointerException:

ParticleSystem system = new ParticleSystem(……);
system.emit(view, 2); // We also postDelay in UI thread
    /** 
          -> emitWithGravity
          -> startEmiting
          -> mTimer.schedule(mTimerTask, 0, TIMMERTASK_INTERVAL);
          -> ParticleTimerTask:run()
          -> ps.onUpdate(ps.mCurrentTime);
          -> mDrawingView.postInvalidate();
          -> NullPointerException (mDrawingView is null)
    **/

though the view is NOT null, there is still has the crash. Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants