Listener for another thread
I have an application that has a GUI and TCP server. The TCP server is running in a different thread and when it receives a certain packet, it should start playing a video file (from MediaPlayer object). The problem is that as a GUI component, the video may be displayed only if invoked from the main thread. I added a listener class to the main class:
Class RequestListener implements NBRequestListener{ /* NBRequestListener is the interface */
public void onRequestArrived(String request) {
processRequest(request); /* This method will run the video */
}
I created a listener in the main thread and set it as a listener in the server:
RequestListener listener = new RequestListener();
server.setRequestListener(listener);
The code in the server is:
public void setRequestListener(_listener) {
listener = _listener; } /* listener is defined as RequestListener */
and the invocation of the event (in the server) is simply:
listener.onRequestArrived(input_from_client);
But the listener me开发者_高级运维thod is invoked in the server thread and not in the main thread and therefore I get exception: java.lang.reflect.InvocationTargetException
. Could you please help pointing the problem?
Multiple ways to solve this one, here's two:
Use a Handler in your Activity. For example, when you get a notification from your background thread, that the video needs to be played, you send a message to your Activity's handler. Code in your custom Handler gets to run on the UI thread. Here's a tutorial (from the many) http://www.helloandroid.com/taxonomy/term/43
When the background thread gets the packet, broadcast an Intent (startBroadcast() on the context class). Register a receiver for this broadcast in your Activity.
The usual way is to have the consumer thread (here, your main thread) wait on a semaphore or a lock, and the producer thread (here, the server thread) release the semaphore or the lock when the resource is available (i.e. when the input from the client has been received).
Have a look at Lock and Semaphore in the java.util.concurrent
and java.util.concurrent.locks
packages.
Many UI require only one thread (the "event" thread) to perform operation on the UI state. This is to prevent concurrency and consistency problems.
When you call a method from another thread, you break this rule. Typically a good solution is to add an event to the event queue that will be executed in the context of the event thread.
In swing it is something like this :
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.
}
});
As you said, you should not block the UI thread, or it will block it.
精彩评论