Categories
android multithreading process

How to pause / sleep thread or process in Android?

318

I want to make a pause between two lines of code, Let me explain a bit:

-> the user clicks a button (a card in fact) and I show it by changing the background of this button:

thisbutton.setBackgroundResource(R.drawable.icon);

-> after let’s say 1 second, I need to go back to the previous state of the button by changing back its background:

thisbutton.setBackgroundResource(R.drawable.defaultcard);

-> I’ve tried to pause the thread between these two lines of code with:

try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

However, this does not work. Maybe it’s the process and not the Thread that I need to pause?

I’ve also tried (but it doesn’t work):

new Reminder(5);

With this:

public class Reminder {

Timer timer;

        public Reminder(int seconds) {
            timer = new Timer();
            timer.schedule(new RemindTask(), seconds*1000);
        }

        class RemindTask extends TimerTask {
            public void run() {
                System.out.format("Time's up!%n");
                timer.cancel(); //Terminate the timer thread
            }
        }  
    }

How can I pause/sleep the thread or process?

3

  • 5

    Oh, just use the classic thread pause block:while (true) {}

    Mar 7, 2010 at 5:54

  • 8

    @KristoferA-Huagati.com I am not sure if you are being sarcastic or indeed there is some Dalvik/Android magic so that this is acceptable on Android. Can you please clarify? Sorry for doubting but I ask because while (!conditionCheck()) {} is usually discouraged.

    May 29, 2012 at 22:08

  • “However, this does not work.” “I’ve also tried (but it doesn’t work)” This is a classic example of saying there’s a problem without giving the symptoms. In what way did these attempts fail to meet your requirements? Did the thread not pause? Did you get an error message?

    – LarsH

    Jul 17, 2017 at 21:52

477

One solution to this problem is to use the Handler.postDelayed() method. Some Google training materials suggest the same solution.

@Override
public void onClick(View v) {
    my_button.setBackgroundResource(R.drawable.icon);

    Handler handler = new Handler(); 
    handler.postDelayed(new Runnable() {
         @Override 
         public void run() { 
              my_button.setBackgroundResource(R.drawable.defaultcard); 
         } 
    }, 2000); 
}

However, some have pointed out that the solution above causes a memory leak because it uses a non-static inner and anonymous class which implicitly holds a reference to its outer class, the activity. This is a problem when the activity context is garbage collected.

A more complex solution that avoids the memory leak subclasses the Handler and Runnable with static inner classes inside the activity since static inner classes do not hold an implicit reference to their outer class:

private static class MyHandler extends Handler {}
private final MyHandler mHandler = new MyHandler();

public static class MyRunnable implements Runnable {
    private final WeakReference<Activity> mActivity;

    public MyRunnable(Activity activity) {
        mActivity = new WeakReference<>(activity);
    }

    @Override
    public void run() {
        Activity activity = mActivity.get();
        if (activity != null) {
            Button btn = (Button) activity.findViewById(R.id.button);
            btn.setBackgroundResource(R.drawable.defaultcard);
        }
    }
}

private MyRunnable mRunnable = new MyRunnable(this);

public void onClick(View view) {
    my_button.setBackgroundResource(R.drawable.icon);

    // Execute the Runnable in 2 seconds
    mHandler.postDelayed(mRunnable, 2000);
}

Note that the Runnable uses a WeakReference to the Activity, which is necessary in a static class that needs access to the UI.

11

  • 3

    It works, but that’s a pretty inconvenient way to introduce delays throughout code, right?

    Jan 20, 2012 at 19:14

  • 4

    I’m not sure what you mean by “inconvenient”. The Handler’s postDelayed method is designed to tell Android that you want a bit of code to be executed after a certain amount of time has passed.

    – tronman

    Feb 16, 2012 at 19:45

  • 27

    after 2 years and this code just helped me! thanks @tronman!! 🙂

    Jun 4, 2012 at 9:53

  • 2

    You can simply copy it to another (final) variable like so final Button mynewbutton = mybutton; and use mynewbutton in the Handler and the Runnable from there on.

    – Dzhuneyt

    May 17, 2013 at 13:19


  • 2

    @MelvinLai after 5 years and this code just helped me! 🙂

    Nov 26, 2015 at 18:13

201

You can try this one it is short

SystemClock.sleep(7000);

WARNING: Never, ever, do this on a UI thread.

Use this to sleep eg. background thread.


Full solution for your problem will be:
This is available API 1

findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(final View button) {
                button.setBackgroundResource(R.drawable.avatar_dead);
                final long changeTime = 1000L;
                button.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        button.setBackgroundResource(R.drawable.avatar_small);
                    }
                }, changeTime);
            }
        });

Without creating tmp Handler. Also this solution is better than @tronman because we do not retain view by Handler.
Also we don’t have problem with Handler created at bad thread 😉

Documentation

public static void sleep (long ms)

Added in API level 1

Waits a given number of milliseconds (of uptimeMillis) before returning. Similar to sleep(long), but does not throw InterruptedException; interrupt() events are deferred until the
next interruptible operation.
Does not return until at least the specified number of milliseconds has elapsed.

Parameters

ms to sleep before returning, in milliseconds of uptime.

Code for postDelayed from View class:

/**
 * <p>Causes the Runnable to be added to the message queue, to be run
 * after the specified amount of time elapses.
 * The runnable will be run on the user interface thread.</p>
 *
 * @param action The Runnable that will be executed.
 * @param delayMillis The delay (in milliseconds) until the Runnable
 *        will be executed.
 *
 * @return true if the Runnable was successfully placed in to the
 *         message queue.  Returns false on failure, usually because the
 *         looper processing the message queue is exiting.  Note that a
 *         result of true does not mean the Runnable will be processed --
 *         if the looper is quit before the delivery time of the message
 *         occurs then the message will be dropped.
 *
 * @see #post
 * @see #removeCallbacks
 */
public boolean postDelayed(Runnable action, long delayMillis) {
    final AttachInfo attachInfo = mAttachInfo;
    if (attachInfo != null) {
        return attachInfo.mHandler.postDelayed(action, delayMillis);
    }
    // Assume that post will succeed later
    ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
    return true;
}

11

  • 22

    And let the Android UI freeze? Don’t do this.

    Aug 10, 2013 at 17:24

  • 3

    Ctrl + Shift + O (Eclipse auto import)

    – Gelldur

    May 17, 2014 at 9:08

  • 14

    Gelldur, you are missing the point of @RichieHH’s comment. Compared to the answer which was accepted 3 years before you posted, what you suggest does not help OP solve his problem. Reason: The code, both as shown by OP, and as shown in the accepted answer, is running inside a UI handler. Saying OMG of course do this in background thread is irrelevant, unless you show HOW to put it in background thread. At which time, you will discover that you have an answer more complicated than the already accepted answer. Did I mention that a better solution was accepted three years ago? 😛

    Sep 12, 2014 at 17:52


  • 2

    … forgot to mention that what makes this suggestion particularly off-purpose to the question, is that OP explicitly wants to do UI action after the delay. So, you would have a solution in which you’ve created a background thread (already more heavy-weight than is needed to solve the problem), slept, and then you have to (somehow) get back to the UI thread. Handler + postRunnable accomplishes all this, in a single step. Without the system overhead of creating a second thread.

    Sep 12, 2014 at 18:01

  • 2

    @ToolmakerSteve happy now 😀 ? Main question is: “How to pause / sleep thread or process in Android?” so my answer was simple :). If someone google for “how to sleep thread” this question will show. He/She is probably looking for my answer :P. But ok i added full response 😉

    – Gelldur

    May 25, 2016 at 8:55

31

I use this:

Thread closeActivity = new Thread(new Runnable() {
  @Override
  public void run() {
    try {
      Thread.sleep(3000);
      // Do some stuff
    } catch (Exception e) {
      e.getLocalizedMessage();
    }
  }
});

4

  • 4

    What is the e.getLocalizedMessage() supposed to do?

    Mar 26, 2012 at 22:28

  • i use e.getLocalizedMessage() when i need a simple, general and quick exception message

    – Byt3

    Mar 30, 2012 at 17:02

  • 1

    But I bet you don’t do this in the situation OP asks about, inside a UI click method, which is going to make further updates to the UI. The accepted Handler/postDelayed solution has two advantages: (1) avoids system overhead of 2nd thread, (1) runs on UI thread, so can make UI changes without causing an exception.

    Sep 12, 2014 at 18:04

  • 1

    Not directly related to the main goal of the question but you shouldn’t catch Exception. Rather catch InterruptedException. By catching Exception, you will catch everything that could go wrong, thus hiding problems that you would otherwise caught.

    – Herve Thu

    Feb 3, 2016 at 21:19