Well, while I would still like to know of a generic/reusable approach to the above, practicality calls. This can also be done by running a Looper on the game thread and then putting the game "event loop stuff" inside the IdleHandler, but I did not like that inversion ..
Here is how I have currently implemented it:
Game/Thread class:
var handler: Handler = _ // handler created on View thread
// Send Message to Looper that exists on View thread
// (Created implicitly for all UI threads.)
def publishEvent(event: OutputEvent) {
handler.obtainMessage(0, event).sendToTarget
}
protected val queue = new ConcurrentLinkedQueue[InputEvent]
def queueEvent(event: InputEvent) { // on UI thread
queue.add(event)
}
def processQueuedEvents() { // on game Thread
@tailrec
def processNextEvent {
val event = queue.poll
if (event ne null) {
doStuffWithInputEvent(event)
processNextEvent
}
}
processNextEvent
}
override def run() { // on game Thread
while (running) {
processQueuedEvents
doOtherGameStuff ~ call_publishEvent ~ etc
}
}
View class:
// Created on UI thread, passed to Game instance
// (The Looper will dispatch Messages to Handlers.)
val handler = new Handler {
override def handleMessage(m: Message) {
val event = m.obj
doStuffWithOutputEvent(event)
}
}
// on UI thread
override def onTouch(v: View, ev: MotionEvent): Boolean = {
// safely queued, will be processed at the start of each game loop
game.queueEvent(InputEvent(..))
}