如果这很容易解决,请原谅。我是调试和解决这种情况的新手。我真的不知道从哪里开始追踪这个问题并确定所涉及的架构。它偶尔发生,似乎更像是一种竞争条件,这取决于我在前一个动画结束后尝试重新启动动画的速度。非常感谢任何指针,并学习一点。
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 to invoke interface method 'void android.animation.Animator$AnimatorListener.onAnimationEnd(android.animation.Animator)' on a null object reference
at android.animation.ValueAnimator.endAnimation(ValueAnimator.java:1239)
at android.animation.ValueAnimator.cancel(ValueAnimator.java:1140)
at android.animation.ObjectAnimator.animateValue(ObjectAnimator.java:974)
at android.animation.ValueAnimator.animationFrame(ValueAnimator.java:1384)
at android.animation.ValueAnimator.doAnimationFrame(ValueAnimator.java:1427)
at android.animation.ValueAnimator$AnimationHandler.doAnimationFrame(ValueAnimator.java:759)
at android.animation.ValueAnimator$AnimationHandler$1.run(ValueAnimator.java:801)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:920)
at android.view.Choreographer.doCallbacks(Choreographer.java:695)
at android.view.Choreographer.doFrame(Choreographer.java:628)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:906)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7229)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
以下是一些关于导致NPE的机制的参考代码。基本上我有一个开始和停止按钮来注册和取消注册光传感器。当注册并发生轻微事件时,我通过锁允许一次调用并启动处理程序/ runnable。当动画结束/完成时,释放锁定以在光事件处理程序中执行另一次执行。
我看到NPE偶尔发生的事情是我在发出先前停止后按START键。它很少发生,正好在STOP发生的边界和START再次发生。
// 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)
{
// do nothing
}
finally
{
try
{
mTweenLock.release();
}
catch (Exception e1)
{
// do nothing
}
}
}
@Override
public void onAnimationCancel(Animator animation)
{
try
{
oa.addListener(null);
oa.addUpdateListener(null);
mMyAppRatingBarLastAlpha = newAlpha;
}
catch (Exception e1)
{
// do nothing
}
finally
{
try
{
mTweenLock.release();
}
catch (Exception e1)
{
// do 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)
{
// do nothing
}
finally
{
mAlphaHandler = null;
}
}
catch(Exception e)
{
try
{
mTweenLock.release();
}
catch (Exception e1)
{
// do nothing
}
}
}
}
// wire up handler and runnable only 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 we press START button in app, fire up the light sensor to 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 we press STOP button in app, we force teardown of everything
try
{
if(mAlphaHandler != null)
{
mAlphaHandler.removeCallbacksAndMessages(null);
mAlphaHandler = null;
runnableAlpha = null;
}
}
catch(Exception e1)
{
// do nothing
}
答案 0 :(得分:0)
问题结果是.onAnimationCancel()被间歇地调用,其中' oa'被设置为null并且随后在.onAnimationCancel()之后调用.onAnimationEnd(),这是架构的工作方式。当.onAnimationEnd被调用时,' oa'此时为NULL导致此NPE。由于.onAnimationEnd()保证在两种情况下都被调用,因此.onAnimationCancel()被拉出来解析NPE。**