android - How to debug and resolve an NPE in AnimatorListener.onAnimationEnd -


please excuse me if simple resolve. i'm new debugging , resolving situations this. i'm not sure begin start tracking down issue , sure of architecture involved. happens sporadically , seems more of race condition based on how fast try refire animation after previous animation ended. appreciate pointers , learn little.

08-08 09:26:01.410 30626-30626/com.myapp.myappname e/androidruntime: fatal exception: main process: com.myapp.myappname, pid: 30626 java.lang.nullpointerexception: attempt invoke interface method 'void android.animation.animator$animatorlistener.onanimationend(android.animation.animator)' on null object reference @ android.animation.valueanimator.endanimation(valueanimator.java:1239) @ android.animation.valueanimator.cancel(valueanimator.java:1140) @ android.animation.objectanimator.animatevalue(objectanimator.java:974) @ android.animation.valueanimator.animationframe(valueanimator.java:1384) @ android.animation.valueanimator.doanimationframe(valueanimator.java:1427) @ android.animation.valueanimator$animationhandler.doanimationframe(valueanimator.java:759) @ android.animation.valueanimator$animationhandler$1.run(valueanimator.java:801) @ android.view.choreographer$callbackrecord.run(choreographer.java:920) @ android.view.choreographer.docallbacks(choreographer.java:695) @ android.view.choreographer.doframe(choreographer.java:628) @ android.view.choreographer$framedisplayeventreceiver.run(choreographer.java:906) @ android.os.handler.handlecallback(handler.java:739) @ android.os.handler.dispatchmessage(handler.java:95) @ android.os.looper.loop(looper.java:158) @ android.app.activitythread.main(activitythread.java:7229) @ java.lang.reflect.method.invoke(native method) @ com.android.internal.os.zygoteinit$methodandargscaller.run(zygoteinit.java:1230) @ com.android.internal.os.zygoteinit.main(zygoteinit.java:1120) 

here reference code regarding mechanics of causing npe. have start , stop button register , unregister light sensor. when registered , light event happens allow 1 call @ time via lock , startup handler/runnable. when animation ends/completes lock released execution in light event handler.

where see npe happening sporadically when go press start after prior stop issued. happens rarely, right @ boundary of stop happening , start happening again.

// on startup of app, prepare runnable runnablealpha = new runnable() {     @override     public void run()     {         try         {             final float newalpha = (.10f * (mlastlightvalue / (mlightsensor.getmaximumrange() / 100)));             final objectanimator oa = objectanimator.offloat(mmyappratingbar, "alpha", mmyappratingbarlastalpha, newalpha);              oa.addlistener(new animatorlistener()             {                 @override                 public void onanimationstart(animator animation)                 {                 }                  @override                 public void onanimationend(animator animation)                 {                     try                     {                         oa.addlistener(null);                         oa.addupdatelistener(null);                         mmyappratingbarlastalpha = newalpha;                     }                     catch (exception e1)                     {                         // nothing                     }                                         {                         try                         {                             mtweenlock.release();                         }                         catch (exception e1)                         {                             // nothing                         }                     }                 }                  @override                 public void onanimationcancel(animator animation)                 {                     try                     {                         oa.addlistener(null);                         oa.addupdatelistener(null);                         mmyappratingbarlastalpha = newalpha;                     }                     catch (exception e1)                     {                         // nothing                     }                                         {                         try                         {                             mtweenlock.release();                         }                         catch (exception e1)                         {                             // nothing                         }                     }                 }                  @override                 public void onanimationrepeat(animator animation)                 {                 }             });              oa.setinterpolator(new decelerateinterpolator());             oa.setduration(1000);             oa.start();              try             {                 if (malphahandler != null)                 {                     malphahandler.removecallbacks(runnablealpha);                 }             }             catch (exception e1)             {                 // nothing             }                         {                 malphahandler = null;             }         }         catch(exception e)         {             try             {                 mtweenlock.release();             }             catch (exception e1)             {                 // nothing             }         }     } }   // wire handler , runnable if light sensor registered, light event triggered, no current lock(prior light event being handled) public void onsensorchanged(sensorevent event) {     if(!mtweenlock.tryacquire())     {         return;     }      try     {         malphahandler = new handler();         mlastlightvalue = event.values[0];          malphahandler.postdelayed(runnablealpha, 0);     }     catch(exception e)     {         malphahandler = null;         mtweenlock.release();     } }  // when press start button in app, fire light sensor begin work msensormanager = (sensormanager) mcontext.getsystemservice(mcontext.sensor_service); mlightsensor = msensormanager.getdefaultsensor(sensor.type_light);  if(mlightsensor == null) {     msensormanager = null;     return; }  msensormanager.unregisterlistener(this, mlightsensor);  // clear out prior if existent msensormanager.registerlistener(this, mlightsensor, sensormanager.sensor_delay_ui);  // when press stop button in app, force teardown of try {     if(malphahandler != null)     {         malphahandler.removecallbacksandmessages(null);         malphahandler = null;         runnablealpha = null;     } } catch(exception e1) {     // nothing } 

the issue turned out .onanimationcancel() intermittently being called wherein 'oa' being set null , .onanimationend() being subsequently called after .onanimationcancel() how architecture works. when .onanimationend called, 'oa' @ point null causing npe. since .onanimationend() guaranteed called in both cases, .onanimationcancel() pulled resolving npe.**


Comments