如何调试和解决AnimatorListener.onAnimationEnd中的NPE



如果这很容易解决,请原谅。我对调试和解决这种情况真的很陌生。我真的不确定从哪里开始追踪这个问题,也不确定所涉及的架构。它偶尔会发生,看起来更像是基于我在前一个动画结束后重新启动动画的速度。非常感谢任何指示和学习一点。

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的机制的参考代码。基本上,我有一个开始和停止按钮来注册和取消注册一个光传感器。当注册并发生轻事件时,我允许通过锁一次调用一个并启动处理程序/可运行程序。当动画结束/完成时,锁被释放,在light事件处理程序中进行另一次执行。

我看到NPE偶尔发生的地方是当我在先前的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
}

问题原来是。onanimationcancel()间歇性被调用,其中'oa'被设置为null和。onanimationend()随后在。onanimationcancel()之后被调用,这就是架构的工作方式。当调用。onanimationend时,此时的'oa'为NULL,导致此NPE。由于. onanimationend()保证在这两种情况下都被调用,所以. onanimationcancel()被提取来解决NPE。**

相关内容

  • 没有找到相关文章

最新更新