43

I want to run some Runnable in a background thread. I want to use Handler because it's convenient for delays. What I mean is

handler.post(runnable, delay);

Where runnable should be run in background Thread. Is it possible to create such Handler? Is there a "background" Looper somewhere or how can I create it?

P.S. I know how to do it with a custom class extends Thread but it requires a little more coding effort than doing it the handler way. So please don't post other solutions or something like

handler.post(new Runnable() {
    @Override
    public void run() {
        new Thread() {
            @Override
            public void run() {
                //action
            }
        }.start();
    }
});

I just wander if Handler can do it the "clean" way.

2
  • You cannot run from background thread other thread. You can do this only from main thread. So if you want to run thread you can use: getActivity().runOnUiThread(new Runnable() { .... here you create new handler. Commented Sep 9, 2013 at 9:04
  • @daro2189 I want to run a background thread from main thread, but delayed. I see that Handler can accept Looper from any thread which has it. I just can't figure if it's possible to create a Looper in background thread. Commented Sep 9, 2013 at 9:08

5 Answers 5

89

You can simply do this:

private Handler mHandler;

private HandlerThread mHandlerThread;

public void startHandlerThread(){
    mHandlerThread = new HandlerThread("HandlerThread");
    mHandlerThread.start();
    mHandler = new Handler(mHandlerThread.getLooper());
}

Then invoke with:

mHandler.postDelayed(new Runnable() {
        @Override
        public void run() {
          // Your task goes here
        }
    },1000);
3
  • 4
    It would be very helpful to add correct sequence to stop all the things. Commented Mar 19, 2018 at 21:06
  • 2
    An if I want to update the UI inside run I need to call runonuithread?
    – David
    Commented Oct 15, 2019 at 10:37
  • for avoid memory leak can use WeakHandler instead Handler; Commented May 27, 2020 at 5:26
10

You can try something like this

    private void createHandler() {
        Thread thread = new Thread() {
            public void run() {
                Looper.prepare();

                final Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                       // Do Work
                        handler.removeCallbacks(this);
                        Looper.myLooper().quit();
                   }
                }, 2000);

                Looper.loop();
            }
        };
        thread.start();
    }
3
  • 1
    This idea is similar to what I did after Yuichi Araki pointed me to the right direction. And the Handler should be assigned to a field, of course. Commented Dec 22, 2014 at 11:55
  • Yeah, just a full example which gather all together. Commented Dec 22, 2014 at 12:04
  • Should we also be performing cleanup of the thread itself after everything is done?
    – Karan
    Commented Jul 22, 2016 at 20:59
5

You can set up a Looper in a background thread using Looper.prepare() and Looper.loop.

2
  • That seems what I wanted. I was looking in the same doc running through methods but somehow I missed the example in the heading of the doc xD. Commented Sep 9, 2013 at 9:19
  • Good Article about [Loopers and Handlers] mindtherobot.com/blog/159/…
    – StepanM
    Commented May 26, 2014 at 15:24
0

Not clear what you mean by Handler.

It sounds like you need a thread that is fed processes to perform by a queue. You would probably benefit from investigating Executors here but here's a simple two-thread pair that communicate through a queue.

public class TwoThreads {
  public static void main(String args[]) throws InterruptedException {
    System.out.println("TwoThreads:Test");
    new TwoThreads().test();
  }
  // The end of the list.
  private static final Integer End = -1;

  static class Producer implements Runnable {
    final Queue<Integer> queue;

    public Producer(Queue<Integer> queue) {
      this.queue = queue;
    }

    @Override
    public void run() {
      try {
        for (int i = 0; i < 1000; i++) {
          queue.add(i);
          Thread.sleep(1);
        }
        // Finish the queue.
        queue.add(End);
      } catch (InterruptedException ex) {
        // Just exit.
      }
    }
  }

  static class Consumer implements Runnable {
    final Queue<Integer> queue;

    public Consumer(Queue<Integer> queue) {
      this.queue = queue;
    }

    @Override
    public void run() {
      boolean ended = false;
      while (!ended) {
        Integer i = queue.poll();
        if (i != null) {
          ended = i == End;
          System.out.println(i);
        }
      }
    }
  }

  public void test() throws InterruptedException {
    Queue<Integer> queue = new LinkedBlockingQueue<>();
    Thread pt = new Thread(new Producer(queue));
    Thread ct = new Thread(new Consumer(queue));
    // Start it all going.
    pt.start();
    ct.start();
    // Wait for it to finish.
    pt.join();
    ct.join();
  }
}
1
  • Thanks for the answer. Executors don't fit since there is only single thread that must be started with a delay, but cancelled if some condition happens before delay is ran out. Handler is perfect for this, but I want to run the Runnable in background, not in Main thread which Handler runs on by default. Commented Sep 9, 2013 at 9:11
0

I implemented simple way of running tasks on background thread in kotlin:

fun background(function: () -> Unit) = handler.post(function)

private val handler: Handler by lazy { Handler(handlerThread.looper) }

private val handlerThread: HandlerThread by lazy {
    HandlerThread("RenetikBackgroundThread").apply {
        setUncaughtExceptionHandler { _, e -> later { throw RuntimeException(e) } }
        start()
    }
}

The general idea is that tasks are simple to execute and running one after other sequentially and uncatched exceptions are propagated to main thread so they don't get lost. Function later is basically handler running on main thread.

So you can post tasks simply like this:

 background {
    some task to do in background...  
 }

some kode

 background {
    other task to do in background...  
    later {
        on main thread when all tasks are finished...
    }
 }

Not the answer you're looking for? Browse other questions tagged or ask your own question.