以下代码更新 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 可以在任何执行点尝试访问已经被破坏的活动的数据成员,如何防止这种情况?
答案 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>