Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to perform a delay on a non-UI Thread in Android

So, there are multiple similar questions/answers about how to do a delay on Android. However they mostly focus on doing this on UI thread. What if I need a delay in a worker thread in a service (and I don't want to put the thread to sleep)? the Handler.postDelayed() doesn't work as there is a "can't create a handler inside thread has not called Looper.prepare()" exception. CountDownTimer doesn't work for the same reason. And I don't have any views to call runOnUiThread(). So is the only solution to have a looper on each thread I have or there is another way to do this?

UPDATE: It's silly, but I found the answer working for me in my own old code :). Basically, if you want to start a Runnable with a delay from a non-UI thread, all you need to do is ask the main looper to handle this.

    Handler handler = new Handler(Looper.getMainLooper());
    Runnable r = new Runnable() {

        @Override
        public void run() {
        // Do stuff to be run after a delay
        // CAUTION: this won't be run on the same thread
        }
    };
    handler.postDelayed(r, DELAY_TIME); 

The drawback could be that the code in that Runnable will not be run on the same thread as the original code. This is why I'm not putting this approach as an answer to be accepted (I admit, the original question sounded like I want a timed event to happen on the same non-UI thread. For this I don't have an answer yet except the one from Emmanuel that I must attach a Looper to my thread). For my purposes however this works as I only need to start a service upon timeout.

like image 450
Dennis K Avatar asked Feb 17 '15 18:02

Dennis K


People also ask

How to run a background thread in Android?

To specify the thread on which to run the action, construct the Handler using a Looper for the thread. A Looper is an object that runs the message loop for an associated thread. Once you've created a Handler , you can then use the post(Runnable) method to run a block of code in the corresponding thread.

What is main thread in Android?

When an application component starts and the application does not have any other components running, the Android system starts a new Linux process for the application with a single thread of execution. By default, all components of the same application run in the same process and thread (called the "main" thread).


1 Answers

Like you have seen from the Exceptions in order to use Handlers in a Thread you need to attach the Thread to the Looper. To give a bit more context, when you call postDelay() you are posting a message to the Thread's MessageQueue; the Looper is responsible for managing this Queue. So if you want to go the Handler route you will need to set up the Thread with a Looper.

If you want to delay the Thread without making it sleep() (I do not know why you cannot use sleep()) you can have a while that runs until a certain time from now has elapsed. (This sounds like a horrible idea).

like image 169
Emmanuel Avatar answered Nov 15 '22 00:11

Emmanuel