简体   繁体   中英

How to return String in anonymous class for a method returning void

I'm bit confused. I have the following:

public static String showInputDialog() {
   Form frm = new Form();
   final Command cmd = new Command("Ok");
   final TextField txt = new TextField("Enter the text", null, 1024, 0);
   frm.addCommand(cmd);
   frm.append(txt);
   frm.setCommandListener(new CommandListener() {

       public void commandAction(Command c, Displayable d) {
            if (c == cmd) {
                return txt.getString(); // Error !!
            } else {
                return null; // Error !!
            }
       }
   });
}

As you can see, I want to return the input dialog string, while the anonymous class method should return void. How can I resolve this problem?

This does not work as you expected.

I see there are already some solutions, but I feel a bit more discussion about what is actually going on might be helpful.

When you call the frm.setCommandListener(new CommandListener() { ... }) the code presents the user with a dialog where she can type in some text and submit, but the code does not stop and wait until the user finishes. Instead the code continues to execute - without yielding the result. Only after the user finished typing and submits, you get called back to process the result - which might happen much later, or not at all.

I guess you have some code calling this method like:

public void someMethod(int foo, String bar) {

   [...]
   String result = MyInputForm.showInputDialog();
   // do something with the result
   System.out.println("hey, got a result "+ result);
   [...]
}

Instead you need to reorganize this. First write a helper class handling the result:

public static class MyCallBack {

   public MyCallBack(... /* here pass in what you need to process the result*/) {
      ... remember necessary stuff in instance variables
   }

   public void processResult(String result) {
      // do something with the result
      System.out.println("hey, got a result "+ result);
      [...]
   }

}

then the calling side does just:

public void someMethod(int foo, String bar) {

   [...]
   MyInputForm.showInputDialog( new MyCallBack(... here pass in stuff ...) );
   [...]
}

and the actual code has to be changed to:

public static String showInputDialog(final MyCallBack callback) {
   Form frm = new Form();
   final Command cmd = new Command("Ok");
   final TextField txt = new TextField("Enter the text", null, 1024, 0);
   frm.addCommand(cmd);
   frm.append(txt);
   frm.setCommandListener(new CommandListener() {

       public void commandAction(Command c, Displayable d) {
            if (c == cmd) {
                return callback.processResult(txt.getString());
            } else {
                return; // or just omit the else part
            }
       }
   });
}

Two issues:

  • this way of programming feels pretty backwards, but it is really the way it works.
  • what feels not right is that I need to define a second helper class aside of the CommandListener . That is really not good style. I hope it can be improved, but as I do not see the complete code (which would be too much information anyway), I have to leave it to you to improve the code and get rid of the clutter. While I feel you want to have a modular, reusable input dialog helper, this might not be the best approach; better define the Form , TextField and Command directly where you need the result and get that running. Make it reusable in a second step after you get it running.

Given that CommandListener is fixed , 2 possible options are

Use a class member variable in the outer class & assign to that variable instead

private static String myText;
...

public static String showInputDialog() {
   ...
   frm.setCommandListener(new CommandListener() {

       public void commandAction(Command c, Displayable d) {
            if (c == cmd) {
                myText = txt.getString(); 
            } else {
                myText = null;
            }
       }
   });
}

or Create a concrete implementation of your CommandListener and set the return value as a property of the new implementation

I would have a look at making the method/variable in this snippet non-static ...

You don't need to return it if you instead do something with the String or store it somewhere, for example:

static String result;

public String commandAction(Command c, Displayable d) {
    if (c == cmd) {
        result = txt.getString();
    } else {
        result = null;
    }
}

Although you'll have threading issues to deal with.

You cant return the string because you dont know when the listener will be called. You can do something with it once you have the string though.

public static void showInputDialog() {

   StringHandler sh = new StringHandler();

   frm.setCommandListener(new CommandListener() {

       public void commandAction(Command c, Displayable d) {
            if (c == cmd) {
                sh.handle(txt.getString()); 
            } else {
                sh.handle(null);
            }
       }
 });}


public class StringHandler {
    public void handle(String s){
        // Do something with that string.
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM