有没有一种方法可以在每个需要更新 ui 组件的函数调用之间延迟几秒钟?

Is there an approach which can delay certain seconds between every function call which need to update ui components?

我正在写一个迷宫游戏,它的特点之一是"Show solution"。解决方案可能包含很多步骤,我用一个for循环来迭代每一步,为了给玩家看得清楚,我希望每一步都能暂停一秒左右。我知道延迟操作不能放在UI线程中,所以我尝试了几种异步延迟方法。不幸的是,由于其异步性质,如果解决方案有多个步骤,则 UI 在最后一步完成之前无法更新。这当然不是我想要的。

我试过handler.postDelayed方法,new Timer().schedule方法。

    public void showSolutionClick(View view) {
        int stage = currentGame.currentStage;
        int[][] solution = GameMap.solutionList[stage];
        drawStage(stage);
        for(int[] step: solution) {
            ImageView v = (ImageView)findViewById(viewIdList[step[0]][step[1]]);
            setTimeout(() -> {v.callOnClick();}, 1);
        }
    }

    private void setTimeout(Runnable r, int seconds) {
        Handler handler = new Handler();
        handler.postDelayed(r, seconds * 1000);
    }

也许同步延迟方法是我需要的,它不能阻止 ui 更新。

更新:CountDownTimer 是针对这种情况的ui表。事实上,我在其他问题上看到了 CountDownTime 的答案,我应该在问之前先尝试这种方法。谢谢所有给予回应的人。这是我的最终代码:

    public void showSolutionClick(View view) {
        int stage = currentGame.currentStage;
        int[][] solution = GameMap.solutionList[stage];
        drawStage(stage);
        int stepTotal = solution.length;
        int stepPause = 1000;
        int timeTotal = (stepTotal + 1) * stepPause;

        new CountDownTimer(timeTotal, stepPause) {
            int stepIndex = 0;
            public void onTick(long timeRemain) {
                int[] pos = solution[stepIndex];
                ImageView v = (ImageView)findViewById(viewIdList[pos[0]][pos[1]]);
                v.callOnClick();
                stepIndex += 1;
                Log.d("time remain:", "" + timeRemain / 1000);
            }

            public void onFinish() {
                Log.d("final step", ":" + (stepIndex - 1));
            }
        }.start();
    }

尝试这样的事情,

public void showSolution(View view) {
// Do something long
Runnable runnable = new Runnable() {
    @Override
    public void run() {
int stage = currentGame.currentStage;
    int[][] solution = GameMap.solutionList[stage];
    drawStage(stage);
    for(int[] step: solution) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            handler.post(new Runnable() {
                @Override
                public void run() {
                       ImageView v = (ImageView)findViewById(viewIdList[step[0]][step[1]]);
        setTimeout(() -> {v.callOnClick();}, 1);
                }
            });
        }
    }
};
new Thread(runnable).start();
}

您可以使用倒数计时器。

 new CountDownTimer(30000, 1000){
                    public void onTick(long millisUntilFinished){
                        doUpdateOnEveryTick()
                    }
                    public  void onFinish(){
                       doActionOnFinish()
                    }
                }.start();