Зачем использовать removeCallbacks() с postDelayed()?
Я пытаюсь понять функциональность, и, в частности, одну конкретную причину, почему мы используем removeCallbacks()
в сочетании с postDelayed()
пройдя по шаблону полноэкранного режима, предоставленному в Android Studio. В полноэкранном шаблоне действий при прикосновении к экрану он показывает / скрывает строку состояния и панель навигации / системную панель через определенное количество миллисекунд, а в случае этого шаблона - 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()
тогда это позволит пользователю спамить методы скрытия / показа. При рассылке спама похоже, что анимация перехода прервана, и что анимация может даже застрять во время спама, потому что она была остановлена в определенной точке во время перехода. Однако, если я позвоню mHideHandler.removeCallbacks(Runnable)
прямо перед postDelayed()
тогда это предотвратит спам пользователей методами скрытия / показа, что хорошо.
Я думаю, вкратце, мой вопрос, как это mHideHandler.removeCallbacks(Runnable)
предотвратить спам, вызываемый при использовании с postDelayed()
? Вопрос похож на этот вопрос, но я надеюсь получить объяснение, почему это происходит.
Вот различия в формате.gif. Использование removeCallbacks() является предполагаемым поведением, а комментирование removeCallbacks() приводит к нежелательному поведению "злоупотребления":
РЕДАКТИРОВАТЬ: Добавлено в.gifs и добавлены комментарии к removeCallbacks() в коде, чтобы помочь определить, о какой части кода я говорю.
1 ответ
Каждый раз, когда вы выполняете клик, вы публикуете событие на MessageQueue
, который будет выполнен после UI_ANIMATION_DELAY
миллисекунды (скажем, это 300 мс).
Теперь, когда вы выполняете последовательные клики, вы публикуете события следующим образом:
SHOW - HIDE - SHOW - HIDE - ...
Если вы не выполняете removeCallbacks()
все эти сообщения будут выполнены, а это означает, что каждый из SHOW
а также HIDE
действия будут выполнены, что приведет к такому глючному поведению.
С другой стороны, при использовании removeCallbacks()
вы говорите, что вы больше не заинтересованы в противоположном событии и не хотите, чтобы это событие выполнялось полностью. Например, если у нас есть ситуация, когда отображаются системные панели, то следующий щелчок инициирует HIDE
событие произойдет через 300 мс, и вы явно говорите, что "эй, если есть какие-то события, которые должны SHOW
системная панель, затем отмените их
handler.removeCallbacks(showRunnable);
handler.postDelayed(hide, 300);
Это дает вам то, что каждый раз, когда вы выполняете последовательные события щелчка, сообщение о противоположном событии, которое уже было размещено в очереди, будет отменено. Это гарантирует, что каждый раз в очереди размещается только 1 сообщение.
Системный интерфейс видим, текущая очередь сообщений:
EMPTY
Клик происходит:
HIDE
Клик происходит:
SHOW (HIDE is being removed from queue)
Клик происходит:
HIDE (SHOW is being removed from queue)
Таким образом, в конце, когда пройдено 300 мс и это сообщение не удалено из очереди, будет выполнено только последнее событие.