0

I want to have a worker thread that can 1) send messages to the UI thread to change things in the GUI, and 2) receive messages from the UI thread to control the worker thread's behavior.

The first part is easy: Create a Handler in the UI thread and let the worker thread send messages to it. Works like a charm. The worker thread uses Thread.sleep() to perform an efficient delay, wakes up to "do things", sends an update to the UI thread's Handler, and repeats.

The next part is apparently difficult in Android. The worker thread must have a Looper to create a Handler so it can RECEIVE messages, and Looper.loop() is a blocking call which means the worker thread is now 100% committed to running the Looper and can't do the other things it is currently doing ("do things", send update message, sleep, repeat).

This implies I need a THIRD thread just to run the Looper for the worker thread, which is ridiculous. It should be possible to have the worker thread do useful things, AND process a message if and when one arrives. This yields an efficient system with the minimum number of thread objects and minimal overhead. I can't figure out how to implement this behavior in Android.

So... how does a worker thread support a Handler and do anything else useful? Thanks!

AndroidNewbie
  • 515
  • 5
  • 17

1 Answers1

2

The worker thread uses Thread.sleep() to perform an efficient delay, wakes up to "do things", sends an update to the UI thread's Handler, and repeats.

It is possible this is the the right thing for your app, but since you decided not to describe your actual business problem, it is difficult to tell. For example, if you were writing an email client, and you needed to get control every 15 minutes to check for new email, your proposed solution would be unreliable.

The next part is apparently difficult in Android

Not especially.

The worker thread must have a Looper to create a Handler so it can RECEIVE messages

Only if you want to use a Handler for that.

Java, as a programming language, has been around for a fairly long time. It has many means of inter-thread communication. Handler, Looper, and HandlerThread wrap around these to offer one particular pattern. That pattern is not suitable for all scenarios, as you have noted. However, the rest of Java still exists, and many standard Java classes are part of Android that you can take advantage of.

So, for example, you could use a LinkedBlockingQueue. Have the main application thread put commands onto that queue. Your worker thread, rather than using sleep(), would use poll() with a timeout to either pull an event from the queue or wake up after a period of time.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Excellent, this is exactly what I was looking for. It reminds me of Completion Ports in Windows, complete with the optional timeout. Android's docs are, not surprisingly, Android-centric so I found no mention of LinkedBlockingQueue. I will begin RTFM immediately... thank you! – AndroidNewbie May 03 '13 at 04:00
  • @AndroidNewbie: "I found no mention of LinkedBlockingQueue" -- it's in the JavaDocs. It's also in various Java resources, like the book "Java Concurrency in Practice". – CommonsWare May 03 '13 at 09:27
  • One questions remains: With several blocking queue mechanisms native to Java, why doesn't Android just use one of them? Why create the whole new Handler/Looper construct when there are several other, existing, native options? – AndroidNewbie May 07 '13 at 01:32
  • @AndroidNewbie: "why doesn't Android just use one of them?" -- performance, from back in the day when Android was targeting single-core 66MHz CPUs. `Handler` is specifically for managing the UI event queue, and there, Android engineers deemed the synchronization overhead would be too much. They exposed `Handler` to us, as an option for our own queuing logic, but it is not designed to be a general-purpose queue solution. – CommonsWare May 07 '13 at 10:35
  • "Android engineers deemed the synchronization overhead would be too much", yet Handler is specifically threadsafe, so the overhead is there in some fashion. Guess I'll chalk it up to the fact that all platforms have their own uniquely weird idiosyncracies. Bottom line: Use Handler to talk to the UI thread and native queues for everything else. Thank you! – AndroidNewbie May 07 '13 at 18:45