Reputation: 17115
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.
Upvotes: 43
Views: 46882
Reputation: 6373
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...
}
}
Upvotes: 0
Reputation: 5761
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);
Upvotes: 89
Reputation: 4220
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();
}
Upvotes: 10
Reputation: 3458
You can set up a Looper in a background thread using Looper.prepare()
and Looper.loop
.
Upvotes: 5
Reputation: 65889
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 Executor
s 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();
}
}
Upvotes: 0