如何让安卓程序“等待”

11

我想让我的程序暂停一定的毫秒数,我应该如何实现?

我已经找到了不同的方法,比如Thread.sleep(time),但我认为那不是我需要的。我只想让我的代码在某一行暂停x毫秒。任何想法都将不胜感激。

这是C语言中的原始代码...

extern void delay(UInt32 wait){
    UInt32 ticks;
    UInt32  pause;

    ticks = TimGetTicks();
    //use = ticks + (wait/4);
    pause = ticks + (wait);
    while(ticks < pause)
        ticks = TimGetTicks();
}

wait是一定数量的毫秒数。


2
你没有提供足够的信息。请解释你的代码是做什么的,以及为什么需要等待/暂停。 - Squonk
1
试图暂停应用程序的主线程可能会触发 ANR。如果您告诉我们您想要做什么,可能会有比阻塞线程更好的解决方案。 - TJ Thind
哈哈,我其实也不知道为什么。我正在将一个Palm Pilot程序转换成Android,它有一个“delay”函数,我会编辑我的原始帖子并向您展示C代码。 - JuiCe
1
@JuiCe:但是delay过程的意义是什么?它在代码的其他部分中是如何使用的,有什么目的? - Squonk
我真的不知道,我要关闭这个问题。在我提问之前,我需要更多地了解正在发生的事情。从我所看到的来看,它只是让程序等待,之前没有调用其他线程。 - JuiCe
8个回答

18
你真的不应该像这样让UI线程休眠,如果你这样做,很可能会导致你的应用程序出现ActivityNotResponding异常而被强制关闭。
如果你想延迟某些代码运行一段时间,请使用Runnable和Handler,例如:
Runnable r = new Runnable() {
    @Override
    public void run(){
        doSomething(); //<-- put your code in here.
    }
};

Handler h = new Handler();
h.postDelayed(r, 1000); // <-- the "1000" is the delay time in miliseconds. 

这样您的代码仍然会被延迟,但您不会“冻结”UI线程,这将在最好的情况下导致性能不佳,最坏的情况下导致ANR强制关闭。


所以你拒绝了编辑建议,甚至不费心在代码的最后一行添加一个分号,这也是编辑建议的主要原因。好吧,那就这样吧。 - FanaticD
@FanaticD 好的伙计,说得好。放松一下。我没有注意到分号,我只看到了几个斜体字。 - FoamyGuy
好的,那么我道歉了。刚才回复得太快了,没有冷静思考的时间。谢谢。 :-) - FanaticD
1
如果您想让可运行文件重复多次怎么办? - Elijah Mock

9
首先,切勿像您正在做的那样使用繁忙循环进行延迟。我可以理解这是从哪里来的——我猜Palm Pilot是一个没有内置sleep()函数的单进程设备,但在多进程设备上,这样的繁忙循环会使整个处理器瘫痪。它会消耗电池,阻止正常系统任务的正确运行,减慢其他程序的速度或完全停止它们,使设备无法响应,甚至可能导致设备在手中发烫。
你需要的调用是Thread.sleep()。你需要设置捕获任何在你睡觉时发生的中断异常。
其次,对于基于事件的用户界面(例如Android或几乎所有现代GUI系统),你永远不要在UI线程中休眠。这也会冻结整个设备并导致ANR(Activity Not Responding)崩溃,如其他帖子中所述。最重要的是,这些小冻结会完全破坏用户体验。
(例外情况:如果您睡眠的时间间隔足够短,用户可能不会注意到,则可以使用。 1/4秒可能还好,但根据情况,可能会使应用程序变得不稳定。)
不幸的是,如果您正在将循环为基础的应用程序移植到基于事件的系统中,则没有清晰而优雅的方法来实现您想要的内容。
尽管如此,正确的做法是在UI线程中创建一个处理程序并向其发送延迟消息。延迟消息将“唤醒”您的应用程序,并触发它在延迟后执行其后续操作。
像这样:
View gameBoard;     // the view containing the main part of the game
int gameState = 0;  // starting
Handler myHandler;

public void onCreate(Bundle oldState) {
  super.onCreate(oldState);
  ...
  gameBoard = findViewById(R.layout.gameboard);
  myHandler = new Handler();
  ...
}

public void onResume() {
  super.onResume();
  displayStartingScreen();
  myHandler.postDelayed(new Runnable() { 
    gotoState1(); 
  }, 250);
}

private void gotoState1() {
  // It's now 1/4 second since onResume() was called
  displayNextScreen();
  myHandler.postDelayed(new Runnable() { 
    gotoState2();
  }, 250);
}
...

顺便说一下,我没有测试过任何那些代码,只是打了进去。让它真正编译起来留给读者作为练习。 - Edward Falk
1
我很感激。我和写手掌代码的那个人交谈了,结果他编写的delay()函数只是为了测试目的,所以我不需要它了。非常感谢你的时间,虽然教给我的东西并没有什么坏处。 - JuiCe

3
您可以使用Handler类和postDelayed()方法来实现这一点:
Handler h =new Handler() ;
h.postDelayed(new Runnable() {
    public void run() {
                 //put your code here
              }

            }, 2000);
}

2000毫秒是在函数内执行代码之前的延迟时间


3
做如下操作。这里有一个参考链接,可能会有帮助。
final MyActivity myActivity = this;   

    thread=  new Thread(){
        @Override
        public void run(){
            try {
                synchronized(this){
                    wait(3000);
                }
            }
            catch(InterruptedException ex){                    
            }

            // TODO              
        }
    };

    thread.start();   

1
SystemClock.sleep(millis)是一个实用函数,与Thread.sleep(millis)非常相似,但它会忽略InterruptedException。

1

不确定为什么您想让程序暂停。如果您希望在后台执行某些任务并使用结果,请查看AsyncTask。我之前也有过类似的问题


0

我认为 Thread.sleep(....) 可能是你想要的,只是你可能没有正确地使用它。你到底想要暂停什么?希望不是 UI 线程吧?我猜你有一些后台线程在某个时间间隔内执行某些任务?如果是这样,那么 Thread.sleep 将使该特定线程在一定时间内休眠,但它不会暂停所有线程。


0
try {
    Thread.sleep(2000); //1000 milliseconds is one second.
}
catch (InterruptedException e) 
{
    e.printStackTrace();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接