Won*_*der 3 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);
}
Run Code Online (Sandbox Code Playgroud)
我知道它removeCallbacks()用于从消息队列中删除待处理的消息/可运行对象,但是除了满足条件并且我们不再希望执行待处理的消息/可运行对象之外,我们是否有特殊原因使用它?
我问这个问题是因为关于全屏活动模板,我在这里有点困惑,因为似乎如果我mHideHandler.removeCallbacks(Runnable)在使用时不调用postDelayed(),那么它将允许用户向隐藏/显示方法发送垃圾邮件。对于垃圾邮件,看起来过渡动画被中断,并且动画甚至可能在垃圾邮件期间卡住,因为它在过渡期间的某个点停止了。mHideHandler.removeCallbacks(Runnable)但是,如果我在此之前调用,postDelayed()它将防止用户向隐藏/显示方法发送垃圾邮件,这很好。
我想简而言之,我的问题是如何mHideHandler.removeCallbacks(Runnable)防止与 一起使用时调用方法的垃圾邮件postDelayed()?问题与这个问题类似,但我希望得到解释为什么会发生这种情况。
以下是 .gif 形式的差异。使用removeCallbacks()是预期的行为,而注释掉removeCallbacks()会导致不需要的“滥用”行为:
编辑:添加到 .gifs 中,并向代码中的removeCallbacks() 添加注释,以帮助识别我正在谈论的代码的哪一部分。
每次执行单击时,您都会向 发布一个事件MessageQueue,该事件将在几毫秒后执行UI_ANIMATION_DELAY(假设是 300 毫秒)。
现在,当您执行连续点击时,您将以这种方式发布事件:
SHOW - HIDE - SHOW - HIDE - ...
Run Code Online (Sandbox Code Playgroud)
如果您不执行removeCallbacks(),所有这些消息都将被执行,这意味着每一个消息SHOW和HIDE操作都将被执行,这会导致这样的错误行为。
另一方面,当使用时,removeCallbacks()您表明您不再对相反的事件感兴趣并且不希望该事件完全执行。例如,如果我们遇到显示系统栏的情况,那么下一次单击将HIDE在 300 毫秒后启动一个事件,并且您明确告知,“嘿,如果发布了一些应该显示SHOW系统栏的事件,那么取消它们”
handler.removeCallbacks(showRunnable);
handler.postDelayed(hide, 300);
Run Code Online (Sandbox Code Playgroud)
这给您带来的是,每次执行连续的单击事件时,已经发布在队列中的相反事件消息都将被取消。这确保每次只有 1 条消息被发布到队列中。
系统UI可见,当前消息队列:
EMPTY
Run Code Online (Sandbox Code Playgroud)
点击发生:
HIDE
Run Code Online (Sandbox Code Playgroud)
点击发生:
SHOW (HIDE is being removed from queue)
Run Code Online (Sandbox Code Playgroud)
点击发生:
HIDE (SHOW is being removed from queue)
Run Code Online (Sandbox Code Playgroud)
因此,最后,当 300ms 过去并且该消息没有从队列中删除时,只会执行最后一个事件。
| 归档时间: |
|
| 查看次数: |
3146 次 |
| 最近记录: |