JAVA - Обозреватель никогда не уведомляется, пока Observable реализован Runnable
У меня есть класс Observable и класс Observer.
Это немного глупо, но метод notifyObserver(arg) моего класса Observable НИКОГДА не вызывает метод update(Observable obj, Object arg) моего класса Observer...
Вот мой НАБЛЮДАЕМЫЙ класс: который извлекает кадр GPS из приемника GPS
public class GPSFrame extends Observable implements Runnable, SerialPortEventListener
{
static Thread myThread;
private CommPortIdentifier portid=null;
private SerialPort serialport;
private BufferedReader fluxgps; // Reading flow port where the GPS is connected
/** CONSTRUCTOR **/
public GPSFrame()
{
myThread=new Thread(this);
}
public void start()
{
// The thread start automatically run() method
myThread.start();
}
@Override
public void run()
{
try
{
// Driver initialization
Win32Driver driver=new Win32Driver();
driver.initialize();
GPSFrame gpscom=new GPSFrame();
gpscom.listPort();
}
catch (Exception e){ System.out.println("start "+e.toString()); }
}
// Scanning all available ports
public void listPort()
{
Enumeration<?> listport=CommPortIdentifier.getPortIdentifiers();
while(listport.hasMoreElements())
{
portid=(CommPortIdentifier)(CommPortIdentifier)listport.nextElement();
if(portid.getPortType()==CommPortIdentifier.PORT_SERIAL)
{
// On lance la gestion des evenements sur le portid
this.portInitialization(portid.getName());
}
}
}
public void portInitialization(String portcom)
{
// ...
}
public void retrieveGpsFrame()
{
String rawframe=new String();
try
{
rawframe=(String)fluxgps.readLine();
String[]gpsframe=rawframe.split(",");
// We are doing a pre-selection of the frame
if(gpsframe[0].equals("$GPGGA") || gpsframe[0].equals("$GPRMC"))
{
/* IMPORTANT - DON'T FORGET SETCHANGED() or GPSFrame'll never
* notify UPDATE() ServerBoard method - We'll never see any changes */
System.out.println(rawframe);
setChanged();
notifyObservers(rawframe);
}
else
{
gpsframe=null;
}
}
catch (IOException e) { e.printStackTrace(); }
}
}
Вот мой класс OBSERVER: который получает и показывает... ничего!
public class ServerBoard extends JFrame implements Observer
{
[...]
// RETRIEVE GPS FRAMES
public void retrieveGPSFrame()
{
gpsframe = new GPSFrame();
gpsframe.addObserver(this);
gpsframe.start();
}
// UPDATE THE JTEXTAREA AND CLIENT
public void update(Observable obj, Object arg)
{
messagearea.append("Affiche moi ce message");
if (arg instanceof String)
{
gpsdata = (String) arg;
System.out.println(gpsdata );
messagearea.append(gpsdata);
tcpserver.sendMessage(gpsdata);
}
}
public void serialEvent(SerialPortEvent event)
{
// Gestion des evenements sur le port
// On ne fait rien sauf quand les donnees sont disponibles
switch(event.getEventType())
{
case SerialPortEvent.DATA_AVAILABLE:
this.retrieveGpsFrame(); // Si les datas sont dispo, on lance la lecture
break;
default:
break; // On ne fait rien sinon
}
}
}
В моем logcat нет ошибок. Когда я запускаю свои приложения в режиме отладки, он никогда не проходит через метод обновления.
Не могли бы вы мне помочь?
Заранее спасибо.
С Уважением,
Tofuw
2 ответа
Я только что нашел мою проблему с тестом.
Я поместил эти строки в мой метод RUN (OBSERVABLE Class):
setChanged();
notifyObservers("Something to show");
И это работает. Класс OBSERVER был уведомлен и показал мне текст в JTextArea. Теперь я просто реорганизовал весь свой код, чтобы сделать это...
Для тех, кто сталкивается с той же проблемой, я опубликую ответ, как только я реорганизовал свой код.
Большое спасибо за ваши ответы в любом случае @xiaowang:)
РЕДАКТИРОВАТЬ: РЕШЕНИЕ
Проблема действительно глупая. Мы просто должны заменить этот метод run()
@Override
public void run()
{
try
{
// Driver initialization
Win32Driver driver=new Win32Driver();
driver.initialize();
GPSFrame gpscom=new GPSFrame();
gpscom.listPort();
}
catch (Exception e){ System.out.println("start "+e.toString()); }
}
Этим:
@Override
public void run()
{
try
{
// Driver initialization
Win32Driver driver=new Win32Driver();
driver.initialize();
this.listPort();
}
catch (Exception e){ System.out.println("start "+e.toString()); }
}
ОБЪЯСНЕНИЕ:
Когда я делаю GPSFrame gpscom=new GPSFrame();
Я создаю новый объект gpscom, родитель которого является моим текущим классом, GPSFrame.
Во время звонка gpscom.listPort();
, это уведомляет наш ТЕКУЩИЙ КЛАСС GPSFrame, а не класс ServerBoard.
Как вы кодируете свой метод notifyObservers(rawframe)?
Попробуйте это исправить двумя способами:
1) проверить
if(gpsframe[0].equals("$GPGGA") || gpsframe[0].equals("$GPRMC"))
{notifyObservers(rawframe);}
выполнил и notifyObservers() вызвал.
2) проверить в notifyObservers(), метод обновления слушателя
update(Observable obj, Object arg)
называется правильно.
Обновить:
Я думаю, что вы не совсем понимаете шаблон проектирования наблюдателя, я беру код из JDK AbstractButton, чтобы помочь вам, посмотреть, как он работает с
//AbstractButton implementation like follwing:
//the button use a ListenerList hold Listeners
protected EventListenerList listenerList = new EventListenerList();
public void addActionListener(ActionListener l) {
listenerList.add(ActionListener.class, l);
}
//notify Listeners to update
protected void fireActionPerformed(ActionEvent event) {
Object[] listeners = listenerList.getListenerList();
ActionEvent e = null;
// Process the listeners last to first, notifying
// those that are interested in this event
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==ActionListener.class) {
((ActionListener)listeners[i+1]).actionPerformed(e);
}
}
}
//observers ,registry to Button, do process in actionPerformed()
JButton btnLogin = new JButton("Login");
btnLogin.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
//do process
}
});