How to pause / sleep thread or process in Android?

AndroidProcessMultithreading

Android Problem Overview


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?

Android Solutions


Solution 1 - Android

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.

Solution 2 - Android

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

Solution 3 - Android

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

Solution 4 - Android

I use CountDownTime

new CountDownTimer(5000, 1000) {
    
    @Override
    public void onTick(long millisUntilFinished) {
        // do something after 1s
    }
    
    @Override
    public void onFinish() {
        // do something end times 5s
    }

}.start(); 

Solution 5 - Android

You probably don't want to do it that way. By putting an explicit sleep() in your button-clicked event handler, you would actually lock up the whole UI for a second. One alternative is to use some sort of single-shot Timer. Create a TimerTask to change the background color back to the default color, and schedule it on the Timer.

Another possibility is to use a Handler. There's a tutorial about somebody who switched from using a Timer to using a Handler.

Incidentally, you can't pause a process. A Java (or Android) process has at least 1 thread, and you can only sleep threads.

Solution 6 - Android

In addition to Mr. Yankowsky's answers, you could also use postDelayed(). This is available on any View (e.g., your card) and takes a Runnable and a delay period. It executes the Runnable after that delay.

Solution 7 - Android

This is what I did at the end of the day - works fine now :

@Override
	public void onClick(View v) {
		my_button.setBackgroundResource(R.drawable.icon);
		// SLEEP 2 SECONDS HERE ...
		final Handler handler = new Handler(); 
        Timer t = new Timer(); 
        t.schedule(new TimerTask() { 
                public void run() { 
                        handler.post(new Runnable() { 
                                public void run() { 
                                 my_button.setBackgroundResource(R.drawable.defaultcard); 
                                } 
                        }); 
                } 
        }, 2000); 
	}

Solution 8 - Android

This is my example

Create a Java Utils

	import android.app.ProgressDialog;
	import android.content.Context;
	import android.content.Intent;

	public class Utils {

		public static void showDummyWaitingDialog(final Context context, final Intent startingIntent) {
			// ...
			final ProgressDialog progressDialog = ProgressDialog.show(context, "Please wait...", "Loading data ...", true);
		
			new Thread() {
				public void run() {
					try{
						// Do some work here
						sleep(5000);
					} catch (Exception e) {
					}
					// start next intent
					new Thread() {
						public void run() {
						// Dismiss the Dialog 
						progressDialog.dismiss();
						// start selected activity
						if ( startingIntent != null) context.startActivity(startingIntent);
						}
					}.start();
				}
			}.start();	
			
		}
		
	}    

Solution 9 - Android

Or you could use:

android.os.SystemClock.sleep(checkEvery)

which has the advantage of not requiring a wrapping try ... catch.

Solution 10 - Android

If you use Kotlin and coroutines, you can simply do

GlobalScope.launch {
   delay(3000) // In ms
   //Code after sleep
}

And if you need to update UI

GlobalScope.launch {
  delay(3000)
  GlobalScope.launch(Dispatchers.Main) {
    //Action on UI thread
  }
}

Solution 11 - Android

I know this is an old thread, but in the Android documentation I found a solution that worked very well for me...

new CountDownTimer(30000, 1000) {

    public void onTick(long millisUntilFinished) {
        mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
    }

    public void onFinish() {
        mTextField.setText("done!");
    }
}.start();

https://developer.android.com/reference/android/os/CountDownTimer.html

Hope this helps someone...

Solution 12 - Android

  class MyActivity{
    private final Handler handler = new Handler();
    private Runnable yourRunnable;
    protected void onCreate(@Nullable Bundle savedInstanceState) {
       // ....
       this.yourRunnable = new Runnable() {
               @Override
               public void run() {
                   //code
               }
            };
       
        this.handler.postDelayed(this.yourRunnable, 2000);
       }

 
     @Override
  protected void onDestroy() {
      // to avoid memory leaks
      this.handler.removeCallbacks(this.yourRunnable);
      }
    }

And to be double sure you can be combined it with the "static class" method as described in the tronman answer

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionHubertView Question on Stackoverflow
Solution 1 - AndroidtronmanView Answer on Stackoverflow
Solution 2 - AndroidGelldurView Answer on Stackoverflow
Solution 3 - AndroidByt3View Answer on Stackoverflow
Solution 4 - AndroidvudandroidView Answer on Stackoverflow
Solution 5 - AndroidDaniel YankowskyView Answer on Stackoverflow
Solution 6 - AndroidCommonsWareView Answer on Stackoverflow
Solution 7 - AndroidHubertView Answer on Stackoverflow
Solution 8 - AndroidStefanoView Answer on Stackoverflow
Solution 9 - AndroidaaaaView Answer on Stackoverflow
Solution 10 - AndroidGuillaumeView Answer on Stackoverflow
Solution 11 - AndroidJohn ByrneView Answer on Stackoverflow
Solution 12 - AndroidbeginnerView Answer on Stackoverflow