我有一个具有GUI和TCP服务器的应用程序。 TCP服务器在不同的线程中运行,当它收到某个数据包时,它应该开始播放视频文件(来自MediaPlayer对象)。问题是,作为GUI组件,只有在从主线程调用时才可以显示视频。我在主类中添加了一个监听器类:
Class RequestListener implements NBRequestListener{ /* NBRequestListener is the interface */
public void onRequestArrived(String request) {
processRequest(request); /* This method will run the video */
}
我在主线程中创建了一个侦听器,并将其设置为服务器中的侦听器:
RequestListener listener = new RequestListener();
server.setRequestListener(listener);
服务器中的代码是:
public void setRequestListener(_listener) {
listener = _listener; } /* listener is defined as RequestListener */
并且事件的调用(在服务器中)只是:
listener.onRequestArrived(input_from_client);
但是侦听器方法在服务器线程中而不是在主线程中调用,因此我得到异常:java.lang.reflect.InvocationTargetException
。你能帮忙指出问题吗?
答案 0 :(得分:1)
解决这个问题的多种方法,这里有两个:
在您的活动中使用处理程序。例如,当您从后台线程收到通知时,需要播放该视频时,您会向Activity的处理程序发送一条消息。自定义处理程序中的代码可以在UI线程上运行。这是一个教程(来自众多)http://www.helloandroid.com/taxonomy/term/43
当后台线程获取数据包时,在上下文类中广播一个Intent(startBroadcast())。在您的活动中注册此广播的接收者。
答案 1 :(得分:0)
通常的方法是让消费者线程(这里是你的主线程)等待信号量或锁定,并且生成器线程(这里是服务器线程)在资源可用时释放信号量或锁定(即当收到来自客户的输入时。)
在java.util.concurrent
和java.util.concurrent.locks
个软件包中查看Lock和Semaphore。
答案 2 :(得分:0)
许多UI只需要一个线程(“事件”线程)来对UI状态执行操作。这是为了防止并发性和一致性问题。
当您从另一个线程调用方法时,您将破坏此规则。通常,一个好的解决方案是将事件添加到将在事件线程的上下文中执行的事件队列。
在摇摆中它是这样的:
SwingUtilities.invokeLater(new Runnable(){
public void run(){
//Your UI code to be run in the context of the event thread.
//In your case linking the video.
}
});
正如你所说,你不应该阻止UI线程,否则它会阻止它。