在调用 removeCallbacks() 时,避免可运行对象内的引用出现空指针异常的推荐设计模式是什么

What is the recommended design pattern to avoid null pointer exceptions on references within a runnable when calling removeCallbacks()

引用下面的代码。 runnable 中的 myRatingBar.setRating 和 myHandler.postDelayed 在调用 stop() 后偶尔会出现空指针异常。我不确定避免这种情况的最佳方法是什么。如果可运行对象包含具有侦听器的对象并且侦听器具有引用,则问题只会变得更糟。

private Handler myHandler;
private Runnable myRunnable;
private RatingBar myRatingBar;

public void start()
{
    myRunnable = new Runnable()
    {
        public void run()
        {
            myRatingBar.setRating(1);
            myHandler.postDelayed(this, 1000);
        }
    }

    myHandler = new Handler();
    myHandler.postDelayed(myRunnable, 0);
}

public void stop()
{
    if(myHandler != null)
    {
        myHandler.removeCallbacksAndMessages(null);
        myHandler = null;
    }

    myRunnable = null;
    myRatingBar = null;
}

添加堆栈跟踪。在此堆栈跟踪中,ValueAnimator onAnimationUpdate 在可运行对象中执行。总体思路是一样的。当 stop() 将其设置为 null 时,runnable 中仍在执行某些内容。

08-07 13:53:21.161: E/AndroidRuntime(20183): 致命异常: main 08-07 13:53:21.161: E/AndroidRuntime(20183): 进程: com.myprocess.myprocess, PID: 20183 08-07 13:53:21.161: E/AndroidRuntime(20183): java.lang.NullPointerException: 尝试在空对象引用上调用虚拟方法 'void android.widget.RatingBar.setLayoutParams(android.view.ViewGroup$LayoutParams)' 08-07 13:53:21.161: E/AndroidRuntime(20183): 在 com.myprocess.myprocess.MyClass2$6$2.onAnimationUpdate(MyClass.java:487) 08-07 13:53:21.161: E/AndroidRuntime(20183): 在 android.animation.ValueAnimator.animateValue(ValueAnimator.java:1283) 08-07 13:53:21.161: E/AndroidRuntime(20183): 在 android.animation.ValueAnimator.animationFrame(ValueAnimator.java:1207) 08-07 13:53:21.161: E/AndroidRuntime(20183): 在 android.animation.ValueAnimator.doAnimationFrame(ValueAnimator.java:1248) 08-07 13:53:21.161: E/AndroidRuntime(20183): 在 android.animation.ValueAnimator$AnimationHandler.doAnimationFrame(ValueAnimator.java:659) 08-07 13:53:21.161: E/AndroidRuntime(20183): 在 android.animation.ValueAnimator$AnimationHandler.run(ValueAnimator.java:682) 08-07 13:53:21.161: E/AndroidRuntime(20183): 在 android.view.Choreographer$CallbackRecord.run(Choreographer.java:777) 08-07 13:53:21.161: E/AndroidRuntime(20183): 在 android.view.Choreographer.doCallbacks(Choreographer.java:590) 08-07 13:53:21.161: E/AndroidRuntime(20183): 在 android.view.Choreographer.doFrame(Choreographer.java:559) 08-07 13:53:21.161: E/AndroidRuntime(20183): 在 android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:763) 08-07 13:53:21.161: E/AndroidRuntime(20183): 在 android.os.Handler.handleCallback(Handler.java:739) 08-07 13:53:21.161: E/AndroidRuntime(20183): 在 android.os.Handler.dispatchMessage(Handler.java:95) 08-07 13:53:21.161: E/AndroidRuntime(20183): 在 android.os.Looper.loop(Looper.java:145) 08-07 13:53:21.161: E/AndroidRuntime(20183): 在 android.app.ActivityThread.main(ActivityThread.java:6141) 08-07 13:53:21.161:E/AndroidRuntime(20183):在 java.lang.reflect.Method.invoke(本机方法) 08-07 13:53:21.161: E/AndroidRuntime(20183): 在 java.lang.reflect.Method.invoke(Method.java:372) 08-07 13:53:21.161: E/AndroidRuntime(20183): 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399) 08-07 13:53:21.161: E/AndroidRuntime(20183): 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)

我不得不想象有更好的方法。如果有人有比我正在做的更好的答案 "cover up" 这个问题,请赐教。这是我现在可耻地做的事情。

private Handler myHandler;
private Runnable myRunnable;
private RatingBar myRatingBar;

public void start()
{
    myRunnable = new Runnable()
    {
        public void run()
        {
            try
            {
                myRatingBar.setRating(1);

                if(myHandler != null)
                {
                    myHandler.postDelayed(this, 1000);
                }
            }
            catch(Exception e)
            {
                // do nothing
            }
        }
    }

    myHandler = new Handler();
    myHandler.postDelayed(myRunnable, 0);
}

public void stop()
{
    if(myHandler != null)
    {
        myHandler.removeCallbacksAndMessages(null);
        myHandler = null;
    }

    myRunnable = null;
    myRatingBar = null;
}