Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android wait() not working

This is my first question here, so please forgive me if I disobeyed any of the forum rules.

I need my program to wait for 3 seconds and then change the Content View

My code is:

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

The program works with no errors, but there is no waiting. When it gets to this part, it just shows the "main" layout without showing the "logout" layout at all.

What is wrong in my approach?

like image 865
george Avatar asked Nov 04 '11 09:11

george


2 Answers

As people noted, don't sleep on or otherwise block the UI thread, but you seem to be aware of this with the new thread you create.

Now for why it doesn't behave as you want:

Right now, you call setContentView(), start a new thread, call setContentView() a second time on the UI thread -- this happens in quick succession with no delay/wait/sleep inbetween. The wait(3000) happens in the new thread you started -- so that new thread starts, waits for 3000ms, then exits. It's an expensive no-op.

You would need to make the second call to setContentView() from inside that new thread's run() method to get the desired effect. Also, you should use sleep() instead of wait() -- wait() is a low-level tool for synchronizing threads while sleep() is the usual "don't continue for X amount of time".

Let me propose a better way:

An arguably nicer and much lighter approch is using Handler.postDelayed() -- this allows you to invoke a Runnable on the UI thread after a delay:

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

Edit to reply to your comment:

Define and find the button before the Runnable as a final variable, this way you can access it later from inside the Runnable.

Please note that to reference the this instance of the surrounding class from inside an anonymous inner class (your new Runnable()), you need to prefix it with the class name of the surrounding class (your Activity class):

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);
like image 123
Philipp Reichart Avatar answered Oct 05 '22 11:10

Philipp Reichart


wait() doesn't wait for a certain amount of time, but rather has the current Thread wait for this to do a notify() for a maximum amount of time. What you are looking for, is Thread.sleep().

And at the moment the only thing that will be waiting, is the additional thread you are spawning, not the activity itself. That's why I'd suggest you look at Handler.postDelayed(), CountDownTimer or AsyncTask. Handling threads is very low-level.

like image 31
Till Helge Avatar answered Oct 05 '22 13:10

Till Helge