JAVA - Observer никогда не уведомляет, пока Observable реализован Runnable

У меня есть класс Observable и класс Observer.

Это немного глупо, но метод notifyObserver(arg) моего класса Observable НИКОГДА не вызывает метод update(Observable obj, Object arg) моего класса Observer...

Вот мой класс OBSERVABLE: который извлекает кадр 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     
        }
    }
}

В моем логарифме ошибок нет. Когда я запускаю свои приложения в режиме отладки, они никогда не проходят метод обновления.

Не могли бы вы мне помочь ?

Заранее спасибо.

С уважением,

тофу


person Tofuw    schedule 06.01.2014    source источник
comment
и notifyObservers звонят?   -  person nachokk    schedule 06.01.2014
comment
Да, notifyObservers вызываются. В этой части нет проблем.   -  person Tofuw    schedule 06.01.2014


Ответы (2)


как вы кодируете свой метод 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

    }
});
person wangdq    schedule 06.01.2014
comment
Привет, спасибо за ответ @xiaowang. Мне не нужно кодировать notifyObserver, потому что это метод Observable. Я проверяю 2 точки, которые вы мне показываете. 1) Нормальное выполнение, и был вызван метод notifyObservers(). 2) метод обновления никогда не вызывался. - person Tofuw; 06.01.2014
comment
вам нужно написать метод notifyObserver, в нем вызвать метод обновления слушателя. смотрите обновление. - person wangdq; 06.01.2014

Я только что нашел свою проблему с тестом.

Я поместил эти строки в свой метод RUN (класс OBSERVABLE):

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.

person Tofuw    schedule 07.01.2014