从Handler Runnable更新销毁的活动UI

时间:2015-08-18 18:11:42

标签: java android multithreading runnable android-handler

以下代码更新 TextView ,直到某个条件的计算结果为false,然后 Handler postDelayed 不再被调用。

但是如果活动被销毁,它会尝试更新null TextView ,处理这个问题的正确方法是什么?我知道我可以对TextView进行防御性空检查,但这仍然不是真正的线程安全。

@Override
protected void onCreate(Bundle savedInstanceState) {
     Handler durationHandler = new Handler();
     durationHandler.postDelayed(updateSeekBarTime, 50);
}

private Runnable updateSeekBarTime = new Runnable() {
            public void run() {

                timeElapsed = mediaPlayer.getCurrentPosition();

                double timeRemaining = finalTime - timeElapsed;

                timeLeft.setText(String.format("%d", TimeUnit.MILLISECONDS.toSeconds((long) timeRemaining)));

                if (timeRemaining >= 1000)
                    durationHandler.postDelayed(this, 200);
            }
        };

换句话说, updateSeekBarTime 可以在任何执行点尝试访问已经被破坏的活动的数据成员,如何防止这种情况?

3 个答案:

答案 0 :(得分:1)

在onResume()中启动处理程序。 在onPause()中使用

停止处理程序
handler.removeCallbacksAndMessages(null); //null removes everything

答案 1 :(得分:1)

我正在构建自己的音乐播放器应用,我使用

durationHandler.removeCallbacks(updateSeekBarTime);
onStop()中的

。它对我有用。

编辑:

通过使用

防止Activity被破坏这一事实帮助了上述这一行
@Override
public void onBackPressed() {
    moveTaskToBack(true);
}

这确保了Activity被最小化而不是被破坏,因此当再次打开时,它非常活泼。

编辑2:

private Runnable updateSeekBarTime = new MyRunnable();

private class MyRunnable extends Runnable {
        private boolean dontWriteText = false;
        @Override
        public void run() {

            timeElapsed = mediaPlayer.getCurrentPosition();

            double timeRemaining = finalTime - timeElapsed;

        if(!dontWriteText)
            timeLeft.setText(String.format("%d", TimeUnit.MILLISECONDS.toSeconds((long) timeRemaining)));

            if (timeRemaining >= 1000)
                durationHandler.postDelayed(this, 200);
        }
        public void dontWriteText() {
            dontWriteText = true;
        }
    };

然后在onDestroy()或onStop()中调用updateSeekBarTime.dontWriteText()。我更喜欢onStop()。

答案 2 :(得分:1)

因此,经过一些代码搜索和阅读博客后,我在Communicating with the UI Thread

的示例代码中找到了答案

即使您可以而且应该从处理程序中删除回调:

handler.removeCallbacksAndMessages(null)

但是上述内容并不能阻止现有运行的Thread访问被破坏的Activity或其视图。

我正在寻找的答案是WeakReference

  

创建对您的TextView或UI元素的弱引用   访问。弱引用可以防止内存泄漏和崩溃,因为   它会自动跟踪"状态"它支持的变量。如果   引用变为无效,弱引用被垃圾收集。   这种技术对于引用属于的对象很重要   组件生命周期。使用硬引用可能会导致内存泄漏   随着价值的不断变化;更糟糕的是,它会导致崩溃   底层组件被销毁。使用弱引用   View确保引用本质上是暂时的。

您仍应检查 null 引用,但现在该活动线程/ runnable将视图设置为 null ,这样您就不会遇到竞争条件。< / p>