Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
135 views
in Technique[技术] by (71.8m points)

java - how to make a custom listener without instantiating the class each time

have a custom listener used for sending a message from one java class to another, however when the listener is used to send a message a new JFrame window is created every time the listener sends a message to the other class, the problem that it ends up being a stack of many Jframe windows.

the reason is that I have to create an instance of the java class for the listener because it is needed to instantiate the listener

 listener = (OnSendResultListener) new ConnectionUtility(false);

so every time the java class sends a short text message to the other java class it creates another ConnectionUtitlity() object and that launches a new JFrame window. not what i want. but if i try to avoid this by passing a boolean perameter in the ConnectionUtility class constructor to determine when the instantiation is real (true) or when the listener is instantiated (false) it will crash. so this does not help either, because removing parts of the class when instantiated for the listener does not allow it to work.

how do i use a simple listener to send messages from one activity to another and alert it to actions, without this having to instantiate the superclass or encapsulating class?

in Android i would use a broadcast receiver for this. but in a java desktop app how to get this to work?

example code for two java classes, MultiThreader and ConnectionUtility

MultiThreader class implements listener and sends message to ConnectionUtility class

 public class MultiThreader {

constructor for class instantiates OnSendResultListener object cast from ConnectionUtility

 public MultiThreader() {

    listener = (OnSendResultListener) new ConnectionUtility(false);
 }

listener interface nested as inner class inside of the MultiThreader class

public interface OnSendResultListener {

   public void onStringResult(String transferString);

}

method for calling listener in MultiThreader class

 public void sendStatus(String status){

     listener.onStringResult(status);

 }

call in MutliThreader class to send string message to ConnectionUtility class by using listener

  sendStatus("File sent to server, Successful");  

connectionUtility class receives messages from MultiThreader class

  public class ConnectionUtility extends javax.swing.JFrame
  implements MultiThreader.OnSendResultListener {

callback method used to receive messages from MultiThrader class and indicate when those messages are received

  @Override
  public void onStringResult(String transferString) {

     jTextArea1.setText(displayString); // sets textArea to string received

 }

EDIT: complete code example shown below for each class

public class MultiThreader implements Runnable {

private Socket socket;
public int fileSizeFromClient;
FileOutputStream fos = null;
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
DataInputStream dis = null;
DataOutputStream dos = null;
ScheduledThreadPoolExecutor stpe;
private OnSendResultListener listener;

public MultiThreader(Socket s) {
    socket = s;
    stpe = new ScheduledThreadPoolExecutor(5);
    listener = (OnSendResultListener) new ConnectionUtility();
}

@Override
public void run() {

    long serialNumber = 0;
    int bufferSize = 0;

     // get input streams
    try {
    bis = new BufferedInputStream(socket.getInputStream());
    dis = new DataInputStream(bis);
    } catch (IOException ex) {
        Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex);
    }

    sendStatus("New connection strarted");

     // read in streams from server
    try {        
        fileSizeFromClient = dis.readInt();
         sendStatus("File size from client " + fileSizeFromClient);
         serialNumber = dis.readLong();
         sendStatus("Serial mumber from client " + serialNumber);
    } catch (IOException ex) {
        Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex);
    }

     try {
        bufferSize = socket.getReceiveBufferSize();
         sendStatus("Buffer size " + bufferSize);
    } catch (SocketException ex) {
        Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex);
    }

    String serialString = String.valueOf(serialNumber);

    File fileDirectory = new File("C:" + File.separator + "DOWNLOAD" + File.separator + serialNumber + File.separator);
    fileDirectory.mkdir();

    File file = new File("C:" + File.separator + "DOWNLOAD" + File.separator + serialNumber + File.separator + "JISSend.pdf");
    try {
        file.createNewFile();
    } catch (IOException ex) {
        Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex);
    }
    try {
    fos = new FileOutputStream(file);
    bos = new BufferedOutputStream(fos);
    dos = new DataOutputStream(bos);
    } catch (FileNotFoundException ex) {
        Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex);
    }

    int count = 0;
    byte[] buffer = new byte[fileSizeFromClient];

    try {

      int totalBytesRead = 0;

       while(totalBytesRead < fileSizeFromClient){
       int bytesRemaining = fileSizeFromClient - totalBytesRead;
       int bytesRead = dis.read(buffer, 0, (int)Math.min(buffer.length, bytesRemaining));

        if(bytesRead == -1){
           break;
         }else{

            dos.write(buffer, 0, bytesRead);
            totalBytesRead += bytesRead;

        }
   }

        } catch (IOException ex) {
            Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex);
        }
        try {

            dos = new DataOutputStream(socket.getOutputStream());

        } catch (IOException ex) {
            Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex);
        }

        stpe.schedule(new CompareFiles(), 0, TimeUnit.SECONDS);
        stpe.schedule(new CloseResources(), 2, TimeUnit.SECONDS);

  } // end run method

  public class CompareFiles implements Runnable {

    @Override
    public void run() {

 int returnInt = 0;
 FileInputStream fis = null;

         File file = new File("C:/DOWNLOAD/JISSend.pdf");
    try {
        fis = new FileInputStream(file);
    } catch (FileNotFoundException ex) {
        Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex);
    }

        int fileLength = (int) file.length();

        sendStatus("Size of database file sent " + fileLength);

         if(fileLength == fileSizeFromClient){

         sendStatus("File sent to server, Successful");   
         returnInt = 1;

         }else if(fileLength != fileSizeFromClient){

         sendStatus("ERROR, file send failed");   
         returnInt = 2;

         }
        try {
            dos.writeInt(returnInt);
        } catch (IOException ex) {
            Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex);
        }

    } // end run method
   } // end of class comparefiles

   public class CloseResources implements Runnable {

    @Override
    public void run() {

    try {
    fos.flush();
    bis.close();
    bos.close();
    dis.close();
    dos.close();
    socket.close();
    } catch (IOException ex) {
            Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex);
    }

    } // end run method
    } // end of class closeResources

 public interface OnSendResultListener {
 public void onStringResult(String transferString);
 }

 public void sendStatus(String status){
 listener.onStringResult(status);
 }

 } // end class multithreader

  public class ConnectionUtility extends javax.swing.JFrame implements
  MultiThreader.OnSendResultListener {

    String  outputLine = "";

    boolean runner = true;
PrintWriter out;
BufferedReader in;
ServerSocket serversocket;
    Socket socket;
    boolean startServer = true;
    public static String displayString = "";

    private ConnectionUtility() {

     initComponents();

     this.startServer = startServer;
     this.setVisible(true);
     serverRunner();

     File fileOne = new File("C:/DBFiles");
     if(!fileOne.exists()){
         fileOne.mkdir();
     }

     File fileTwo = new File("C:/DBFilesOut");
     if(!fileTwo.exists()){
         fileTwo.mkdir();
     }  

 }

@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">                          
 private void initComponents() {

    jLabel1 = new javax.swing.JLabel();
    jScrollPane1 = new javax.swing.JScrollPane();
    jTextArea1 = new javax.swing.JTextArea();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

    jLabel1.setFont(new java.awt.Font("MS UI Gothic", 0, 36)); // NOI18N
    jLabel1.setText("TankInspectionSystem");

    jTextArea1.setColumns(20);
    jTextArea1.setRows(5);
    jScrollPane1.setViewportView(jTextArea1);

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addGap(72, 72, 72)
            .addComponent(jLabel1)
            .addContainerGap(76, Short.MAX_VALUE))
        .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
            .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 383, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addGap(37, 37, 37)
            .addComponent(jLabel1)
            .addGap(34, 34, 34)
            .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 179,   javax.swing.GroupLayout.PREFERRED_SIZE)
            .addContainerGap(37, Short.MAX_VALUE))
    );

    pack();
}// </editor-fold>                        

 // Variables declaration - do not modify                     
 private javax.swing.JLabel jLabel1;
 private javax.swing.JScrollPane jScrollPane1;
 private javax.swing.JTextArea jTextArea1;
 // End of variables declaration                   

 public void serverRunner(){

      runner = true;

       try {
        serversocket = new ServerSocket(6789, 100);

         System.out.println();

    } catch (IOException ex) {
        Logger.getLogger(ConnectionUtility.class.getName()).log(Level.SEVERE, null, ex);
    }

      while(runner){

         try {
             socket = serversocket.accept();

  addAndDisplayTextToString("new connection, inet socket address >>> " + socket.getPort());
  System.out.println(displayString);


         } catch (IOException ex) {
             Logger.getLogger(ConnectionUtility.class.getName()).log(Level.SEVERE, null, ex);
         }

           MultiThreader multi = new MultiThreader(socket);
           Thread t = new Thread(multi);
           t.start();

      }  // end while runner loop

 } // end serverRunner method

 public static void addAndDisplayTextToString(String setString){

   StringBuilder stb = new StringBuild

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If you only want a single instance of an object no matter where you call it, do:

public class MyObject {

    private static MyObject instance;

    public static MyObject getInstance(..) {
        if (instance != null) {
            return instance;
        }
        return instance = new MyObject(..);
    }

    // private constructor to avoid new instances 
    private MyObject(..) { .. }
}

MyObject anObject = MyObject.getInstance(..); // always returns the same instance

The '..' indicate arbitrary parameters. I usually pass a Context upon construction and from thereon use setters on the object to manipulate it depending on what I want it to do e.g. setMessage(..) to change output or setCallListener(..) to redirect callbacks to another object.

Not sure this is what you are looking for but had the feeling it was something like this.

Edit:

After seeing your code, then how about in ConnectionUtility :

MultiThreader multi = new MultiThreader(socket, this);

And in MultiThreader:

public MultiThreader(Socket s, OnSendResultListener resultListener) {
    socket = s;
    stpe = new ScheduledThreadPoolExecutor(5);
    listener = resultListener;
}

Note that the single instance method should also work, just think this might be the simplest solution as you can pass it directly using this (since implementing the right interface).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...