Как использовать Handler Postdelayed в очереди? - PullRequest
0 голосов
/ 27 августа 2018

У меня есть ситуация, я создал кнопку и такую ​​функцию.

...
public void BtnOnClick(View view) {

    displayMsg();
}

...

private void displayMsg(){
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            Toast.makeText(this, "TestQueue", Toast.LENGTH_SHORT).show();

        }
    }, 3000);

}
...

Если я нажму кнопку один раз, тост появится через 3 секунды. Но если я быстро нажму кнопку два или более раз, то все тосты появятся одновременно через 3 секунды без задержки в 3 секунды между каждым тостом, это не хорошо. Я хочу, чтобы между каждым появлением тоста была задержка / задержка в 3 секунды, несмотря на одновременные щелчки.

Есть ли решение?

Если в очереди несколько обработчиков, то время задержки каждого обработчика начинается после окончания времени задержки предыдущего обработчика.

Ответы [ 4 ]

0 голосов
/ 27 августа 2018

Попробуйте это:

private final Handler handler = new Handler() {

    final int DELAY = 3000;
    final int DELAY_MSG = 1;
    final Queue<Runnable> pendingRunnables = new ArrayDeque<>();

    @Override
    public void dispatchMessage(Message msg) {
        if (msg.what == DELAY_MSG) {
            final Runnable r = pendingRunnables.poll();
            if (r != null) {
                r.run();
                sendEmptyMessageDelayed(DELAY_MSG, DELAY);
            }
        } else {
            pendingRunnables.add(msg.getCallback());
            if (!hasMessages(DELAY_MSG)) {
                sendEmptyMessage(DELAY_MSG);
            }
        }
    }
};

...

// post action
handler.post(new Runnable() {
    @Override
    public void run() {
        Toast.makeText(this, "TestQueue", Toast.LENGTH_SHORT).show();
    }
});
0 голосов
/ 27 августа 2018

Вы можете поставить в очередь запросы, чтобы убедиться, что тосты отображаются с интервалом.

ArrayList<Runnable> requests = new ArrayList<>;
bool inProgress = false;
private void displayMsg(){
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            Toast.makeText(this, "TestQueue", Toast.LENGTH_SHORT).show();
            inProgress = false;
            if (requests.size() > 0) {
                handler.postDelayed(requests.remove(0), 3000 + Toast.LENGTH_SHORT);
            }
        }
    }
    if (!inProgress) {
        inProgress = true;
        handler.postDelayed(runnable, 3000);
    } else {
        requests.add(runnable);
    }
}
0 голосов
/ 27 августа 2018

Решение: Вы можете использовать postDelayed для решения вашей проблемы:

private long interval = 0;

public void BtnOnClick(View view) {
    displayMsg();
}

private void displayMsg() {
    interval += 3000;
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            Toast.makeText(this, "TestQueue", Toast.LENGTH_SHORT).show();
        }
    }, interval);
}
0 голосов
/ 27 августа 2018

Может быть, вы можете использовать postAtTime:

AtomicLong previous = new AtomicLong(System.currentTimeMillis());

private void displayMsg(){
    handler.postAtTime(new Runnable() {
        @Override
        public void run() {
            Toast.makeText(this, "TestQueue", Toast.LENGTH_SHORT).show();
        }
    }, previous.updateAndGet(operand -> Long.max(operand + 3000, System.currentTimeMillis() + 3000)));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...