Android 线程游戏中的演员/消息传递”;事件循环“;
我正在构建一个Android应用程序(使用Scala 2.9)并使用一个线程渲染到SurfaceView;这是一个游戏,所以它应该经常更新。我认为这个问题类似于其他游戏“事件循环”,其中输入来自不同的线程 下面是当前依赖于同步的方法的大致近似值。它“工作得很好”,但我对必须使用显式同步和“捆绑”视图/输入线程有普遍的疑虑 视图,“UI线程”: 游戏,“游戏线程”: 我不希望显式使用同步,而是希望有如下内容:Android 线程游戏中的演员/消息传递”;事件循环“;,android,multithreading,scala,actor,game-loop,Android,Multithreading,Scala,Actor,Game Loop,我正在构建一个Android应用程序(使用Scala 2.9)并使用一个线程渲染到SurfaceView;这是一个游戏,所以它应该经常更新。我认为这个问题类似于其他游戏“事件循环”,其中输入来自不同的线程 下面是当前依赖于同步的方法的大致近似值。它“工作得很好”,但我对必须使用显式同步和“捆绑”视图/输入线程有普遍的疑虑 视图,“UI线程”: 游戏,“游戏线程”: 我不希望显式使用同步,而是希望有如下内容: def View.onTouchEvent(e) { // on UI thread
def View.onTouchEvent(e) { // on UI thread
Game.sendMessage(e)
}
def Game.run () { // on Game thread
while (running) {
processMessage
doGameStuff
View.sendMessage(someState) // hopefully same as Game.sendMessage
yield
}
}
现在,使用ConcurrentLinkedQueue
或类似工具手动实现这一点相对容易,但我真的不想在这里重新发明轮子。此外,使用这样一个参与者/队列来发回UI也很好——现在我正在使用Android的支持向UI线程发回(异步)可运行的消息
我简要介绍了几种不同的actor实现(主要是标准Scala和Scalaz)和一些不同的Java“消息传递”库,例如,但大多数似乎使用隐式线程或线程执行器服务。但是,在我的例子中,我希望在特定线程上的特定时间[运行actor并]处理消息。对于View.sendMessage,消息也应该在UI线程上处理,但计时并不重要,可以借助上面提到的可运行执行
那么,我想我的问题是,鉴于上述情况:
在这两个线程之间提供数据的“高效”和惯用方法是什么
(我也愿意接受这样的建议,即我完全无法理解Scala actors和/或Scalaz actors和/或其他消息传递库;Scalaz似乎可以按照我的设想工作,但我很难遵循。)好吧,尽管我仍然想知道一种通用/可重用的方法来处理上述问题,实用性要求。这也可以通过在游戏线程上运行一个,然后将游戏“事件循环东西”放在IdleHandler中来实现,但我不喜欢这种反转
以下是我目前如何实现它的:
游戏/线程类:
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
}
}
视图类:
// 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(..))
}
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
}
}
// 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(..))
}