为什么要将removeCallbacks()与postDelayed()一起使用?

时间:2017-07-05 08:59:11

标签: java android handler runnable postdelayed

我尝试了解功能,特别是我们通过浏览Android Studio中提供的全屏活动模板将removeCallbacks()postDelayed()结合使用的一个特定原因。在全屏活动模板中,当触摸屏幕时,它将在一定的毫秒数后显示/隐藏状态栏和导航/系统栏,并且在此模板的情况下为3000毫秒。

private void hide() {
    // Hide UI first
    ActionBar actionBar = getSupportActionBar();
    if (actionBar != null) {
        actionBar.hide();
    }
    mControlsView.setVisibility(View.GONE);
    mVisible = false;

    // Schedule a runnable to remove the status and navigation bar after a delay
    mHideHandler.removeCallbacks(mShowPart2Runnable); // <------ Comment/uncomment
    mHideHandler.postDelayed(mHidePart2Runnable, UI_ANIMATION_DELAY);
}

@SuppressLint("InlinedApi")
private void show() {
    // Show the system bar
    mContentView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
    mVisible = true;

    // Schedule a runnable to display UI elements after a delay
    mHideHandler.removeCallbacks(mHidePart2Runnable); // <------ Comment/uncomment
    mHideHandler.postDelayed(mShowPart2Runnable, UI_ANIMATION_DELAY);
}

/**
 * Schedules a call to hide() in [delay] milliseconds, canceling any
 * previously scheduled calls.
 */
private void delayedHide(int delayMillis) {
    mHideHandler.removeCallbacks(mHideRunnable); // <------ Comment/uncomment
    mHideHandler.postDelayed(mHideRunnable, delayMillis);
}

我了解removeCallbacks()用于从消息队列中删除待处理消息/ runnables,但除了符合条件之外,我们还有一个特殊原因可以使用它我们不再希望执行挂起的消息/ runnables吗?

我问这个问题,因为关于全屏活动模板我在这里感到困惑,因为如果我在使用mHideHandler.removeCallbacks(Runnable)时没有打电话给postDelayed()那么它就会#39} ; ll允许用户垃圾邮件隐藏/显示方法。随着垃圾邮件的发送,过渡动画似乎被中断,并且动画甚至可能在垃圾邮件期间卡住,因为它在转换期间的某个时刻停止了。但是,如果我在mHideHandler.removeCallbacks(Runnable)之前拨打postDelayed(),那么它会阻止用户发送隐藏/显示方法,这很好。

我想简而言之,我的问题是mHideHandler.removeCallbacks(Runnable)如何防止在与postDelayed()一起使用时调用方法的垃圾邮件?问题类似于question,但我希望得到解释为什么会发生这种情况。

以下是.gif格式的差异。使用removeCallbacks()是注释掉removeCallbacks()导致不想要的&#34;滥用&#34;行为:

With removeCallbacks()

Without removeCallbacks()

编辑:在.gifs中添加并在代码中的removeCallbacks()中添加了注释,以帮助识别我正在谈论的代码的哪一部分。

1 个答案:

答案 0 :(得分:3)

每次执行点击时,您都会向MessageQueue发布一个事件,该事件将在UI_ANIMATION_DELAY毫秒后执行(假设它是300毫秒)。

现在,当您执行连续点击时,您将以这种方式发布事件:

SHOW - HIDE - SHOW - HIDE - ...

如果您不执行removeCallbacks(),则会执行所有这些消息,这意味着将执行每个SHOWHIDE操作,这会导致这种不良行为

另一方面,当使用removeCallbacks()时,您告诉您不再对相反的事件感兴趣,并且不希望该事件完全执行。例如,如果我们遇到系统栏显示的情况,那么下一次点击会在300毫秒后发出HIDE事件并且您明确告诉,“嘿,如果有某些事件张贴应该SHOW系统栏,然后取消它们“

handler.removeCallbacks(showRunnable);
handler.postDelayed(hide, 300);

这给您带来的是,每次执行连续点击事件时,队列中已发布的相反事件消息将被取消。这可以确保每次只有1条消息发布在队列中。

系统UI可见,当前消息队列:

EMPTY

点击发生:

HIDE

点击发生:

SHOW (HIDE is being removed from queue)

点击发生:

HIDE (SHOW is being removed from queue)

因此,最后,当传递300ms并且不从队列中删除此消息时,只会执行最后一个事件。