JAVA - 在Observable实现Runnable时,Observer永远不会被通知

时间:2014-01-06 14:58:20

标签: java observable observers

我有一个Observable类和一个Observer类。

这有点傻,但我的Observable类的方法notifyObserver(arg)永远不会调用我的Observer类的更新(Observable obj,Object arg)方法......

这是我的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     
        }
    }
}

我的logcat中没有错误。 当我在调试模式下启动应用程序时,它永远不会通过更新方法。

你能帮我吗?

事先,谢谢。

此致

Tofuw

2 个答案:

答案 0 :(得分:0)

您如何编码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

    }
});

答案 1 :(得分:0)

我刚刚发现了测试问题。

我把这些行放在我的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();时,它会通知我们的CURRENT CLASS GPSFrame,而不是ServerBoard类。