【问题标题】:Android wait() not workingAndroid等待()不起作用
【发布时间】:2011-11-04 09:37:34
【问题描述】:

这是我在这里的第一个问题,如果我违反了任何论坛规则,请原谅我。

我需要我的程序等待 3 秒,然后更改内容视图

我的代码是:

setContentView(R.layout.logout); 

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

setContentView(R.layout.main);

程序可以正常运行,但无需等待。当它到达这部分时,它只显示“主”布局,根本不显示“注销”布局。

我的方法有什么问题?

【问题讨论】:

    标签: android multithreading handler wait


    【解决方案1】:

    正如人们所说,不要睡在 UI 线程上或以其他方式阻塞 UI 线程,但您似乎通过创建的新线程意识到了这一点。

    现在说明为什么它的行为不符合您的要求:

    现在,您调用 setContentView(),启动一个新线程,在 UI 线程 上再次调用 setContentView() -- 这会快速连续发生,中间没有延迟/等待/睡眠. wait(3000) 发生在您启动的新线程中——所以 新线程 启动,等待 3000 毫秒,然后退出。这是一个昂贵的无操作。

    您需要从 inside 新线程的 run() 方法对 setContentView() 进行第二次调用,以获得所需的效果。此外,您应该使用 sleep() 而不是 wait() -- wait() 是用于同步线程的低级工具,而 sleep() 是通常的“不要继续 X 时间”。

    让我提出一个更好的方法:

    一个可以说更好更轻的方法是使用Handler.postDelayed()——这允许您在延迟后调用 UI 线程上的 Runnable:

    setContentView(R.layout.logout);
    new Handler().postDelayed(new Runnable() {
        @Override
            public void run() {
                setContentView(R.layout.main);
            }
        }, 3000);
    

    编辑以回复您的评论:

    将 Runnable 之前的按钮定义并查找为 final 变量,这样您以后可以从 Runnable 内部访问它。

    请注意,要从匿名内部类(您的 new Runnable())内部引用周围类的 this 实例,您需要在其前面加上周围类的类名(您的 Activity 类) :

    final View submitButton = findViewById(R.id.submit_button); 
    setContentView(R.layout.logout);
    new Handler().postDelayed(new Runnable() {
        @Override
            public void run() {
                setContentView(R.layout.main);
                // adapt to your actual Activity class name:
                submitButton.setOnClickListener(YourClassName.this);
            }
        }, 3000);
    

    【讨论】:

    • 谢谢 vm 这行得通。但是当它返回到“主”布局时,我如何添加一个监听器呢?我的意思是我有一个按钮,我想添加如下内容: View submitButton = findViewById(R.id.submit_button); submitButton.setOnClickListener(this);我无法在 run 方法中执行此操作,如果在此之后执行此操作,则会出现错误
    • 我做到了。我刚刚从运行(设置)中调用了另一个方法,我设置了侦听器。它工作正常,但我不知道我是否使用了良好的做法(抱歉,对 android 来说有点新)
    • 这与从可运行文件外部传入最终变量基本相同——在这两种情况下,VM 都会合成一些代码来访问变量/方法。没关系。选择对您来说最易读的内容:)
    • 你的方法也很好用! P.S:谢谢大家的回答!我想对其中一些投票 +,但上面写着“投票需要 15 声望”
    • 很高兴为您提供帮助!很高兴你想投票 - 等到你得到必要的代表,然后回到你的旧问题来投票/接受答案。别担心,如果你忘记了,这里的人会提醒你的;)
    【解决方案2】:

    wait() 不会等待一定时间,而是让当前线程等待this 执行notify() 最长时间。你要找的是Thread.sleep()

    目前唯一等待的是您正在生成的附加线程,而不是活动本身。这就是为什么我建议您查看Handler.postDelayed()CountDownTimerAsyncTask。处理线程是非常底层的。

    【讨论】:

    • +1 表示等待/睡眠差异。 Timer/AsyncTask 可能是矫枉过正(性能和代码方面),Handler.postDelayed() 似乎是要走的路。
    【解决方案3】:

    您的代码无法休眠 UI 线程。要休眠 UI 线程,请尝试此代码

    new Handler().postDelayed(new Runnable() 
    { 
        public void run() 
        { 
            setContentView(R.layout.main);
        }
    }, 3000);
    

    【讨论】:

      【解决方案4】:

      尝试使用 Sleep() 而不是 Wait()

      android.os.SystemClock.sleep(3000)

      【讨论】:

      • 不要在主事件循环线程上休眠。这将使应用程序无响应。
      • 谢谢你的答案。这在等待方面有效,但不是我想要的方式:setContentView(R.layout.logout); android.os.SystemClock.sleep(3000);设置内容视图(R.layout.main);在确实显示“主”布局之前等待 3 秒,但它不显示“注销”布局
      【解决方案5】:

      据我所知,等待发生在新线程中,您在当前线程中调用 setContentView(R.layout.main)。

      试试

      setContentView(..)
      synchronized(this) {
          this.wait(1000);
      }
      setContentView(..)
      

      请注意,在 UI 线程中休眠或等待并不是最佳做法。

      【讨论】:

      • 不要在主事件循环线程上休眠(或等待)。这将使应用程序无响应。
      猜你喜欢
      • 2020-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-15
      • 2017-07-17
      • 2019-04-14
      • 1970-01-01
      相关资源
      最近更新 更多