0

Bitte entschuldigen Sie, wenn dies einfach zu lösen ist. Ich bin wirklich neu im Debuggen und Lösen von Situationen wie dieser. Ich bin mir wirklich nicht sicher, wo ich anfangen soll, dieses Problem aufzuspüren, und ich bin sicher, dass es sich um die Architektur handelt. Es passiert sporadisch und scheint mehr wie eine Race-Bedingung zu sein, basierend darauf, wie schnell ich versuche, die Animation nach dem Ende der vorherigen Animation neu zu starten. Sehr schätzen Sie alle Hinweise und lernen ein wenig.Wie Debuggen und Auflösen einer NPE in AnimatorListener.onAnimationEnd

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) 

Hier ist ein Referenzcode über die Mechanik der NPE. Im Wesentlichen habe ich eine Start- und eine Stopp-Taste, um einen Lichtsensor zu registrieren und die Registrierung aufzuheben. Wenn registriert und ein Lichtereignis passiert, erlaube ich jeweils einen Anruf über eine Sperre und starte einen Handler/Runnable. Wenn die Animation beendet/abgeschlossen ist, wird die Sperre für eine weitere Ausführung in dem Ereignis-Handler freigegeben.

Wo sehe ich die NPE sporadisch passiert, wenn ich START drücken, nachdem ein vorheriger STOP ausgegeben wurde. Es passiert selten, direkt an der Grenze eines STOP Happening und START passiert wieder.

// 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

Wo ist ein Code? –

+0

Lassen Sie mich wissen, welchen Code Sie gerne sehen würden. Angenommen, nur das Setup und der Abbau der Animation? – user1701153

+0

Ja, und Animation zu –

Antwort

0

Die Frage stellte sich heraus, .onAnimationCancel() intermittierend aufgerufen wird sein, wobei ‚o‘ eingestellt wurde auf null und .onAnimationEnd() nach .onAnimationCancel() anschließend wird aufgerufen, die ist, wie die Architektur funktioniert. Wenn .onAnimationEnd aufgerufen wurde, ist 'oa' an diesem Punkt NULL, was diese NPE verursacht. Da .onAnimationEnd() in beiden Fällen garantiert aufgerufen wird, wurde die .onAnimationCancel() zur Auflösung der NPE herangezogen. **