如何在队列中延迟使用处理程序?

时间:2018-08-27 12:56:24

标签: java android multithreading handler task-queue

我有一个情况,我创建了一个按钮和一个类似这样的功能。

...
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秒钟的延迟后应该出现一个Toast。 但是,如果我快速单击按钮两次或两次以上,则所有Toast会在3秒后同时出现,而在每次Toast之间都不会延迟3秒,这不好。尽管希望同时点击,但我希望每个Toast外观之间的间隔/延迟为3秒。

有什么解决办法吗?

如果队列中有多个处理程序,则每个处理程序延迟时间在上一个处理程序延迟时间结束之后开始。

4 个答案:

答案 0 :(得分:1)

您可以将请求排入队列,以确保间隔显示面包。

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);
    }
}

答案 1 :(得分:1)

尝试一下:

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();
    }
});

答案 2 :(得分:0)

也许您可以使用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)));
}

答案 3 :(得分:0)

解决方案::您可以使用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);
}