有没有一种方法可以在每个需要更新 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();
我正在写一个迷宫游戏,它的特点之一是"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();