How Do I pass a @SimpleEvent name as a parameter to a private Function?

Oh I understand, so you want to be able to take a method, that you would call later right?

3 Likes

try GetOutput(output);

i am confused this time

In here, the event name is unknown. For example, in App Inventor, you can track the user input, which is strings, and open another screen with that string because App Inventor opening screens accept strings. But in Java, they cannot do something like

"GetOutput"(output);

and it must be

GetOutput(output);

. Probably this.

1 Like

Here I have simplified to working code. You can see GotOutput is hard coded in GetFunction and will therefore run the event. But i will have many simpleevents and simplefunctions, so i want to be able to substitute GotOutput for whatever simpleevent is needed for the desired simplefunction. All simplefunctions will call GetFunction.

@SimpleEvent(description = "Event raised when output returned")
  public void GotOutput(final String output) {
    EventDispatcher.dispatchEvent(this, "GotOutput", output);
  }

@SimpleFunction(description = "set parameters to get output")
  public void GetOutput() {
      String parameters = "some parameters";
      GetFunction(parameters);
  }

private void GetFunction(String parameters) {
//do something
//output to event:
GotOutput(output);
}
1 Like

only have one GotOutput event, which will fire for all those many simple functions
Taifun

2 Likes

Yes, I have done this, but it generates work elsewhere to identify which simplefunction was called. Could be the easiest route though :slight_smile:

1 Like

Probably you have to hard code the functions, like this.

You have these events

@SimpleEvent(description = "Event raised when output returned")
  public void GotOutput(final String output) {
    EventDispatcher.dispatchEvent(this, "GotOutput", output);
  }

@SimpleEvent(description = "Event raised when output result")
  public void GotResult(final String output) {
    EventDispatcher.dispatchEvent(this, "GotOutput", output);
  }

and you do this.

if (something == "GotOutput") {
GotOutput(output);
} else if (something == "GotResult") {
GotResult(result);
}
2 Likes

Yes I could build an if/else block or a switch-case statement to handle things. :slight_smile:

2 Likes

just pass that name to GotOutput and use it in the event as output parameter
Taifun

2 Likes

Do you want to call a function / method by its name?

1 Like

That is the idea, but to pass it as a parameter ....

2 Likes

Yes. Unfortunately in Java you cannot do

and you cannot do

TextView "myTextViewCreatedJustNow" = new TextView;

and Tim also wants to

as well. It would certainly have challenges.

1 Like

You might try reflection?

2 Likes

Interesting.

This particularly comes in handy when we don't know their names at compile time.

1 Like

Check this, call a function by its name and pass parameters:

I have been thinking about this for sometime :smiley: (this is a joke)

I have seen reflection being used for this on StackOverflow, but the application of the approach was way over my head. :upside_down_face:

1 Like

You wont be able to simply pass the method in Java, you could use easy conditions instead.
But still, a similar thing can be done:

package xyz.kumaraswamy.test;

import com.google.appinventor.components.annotations.SimpleEvent;
import com.google.appinventor.components.annotations.SimpleFunction;
import com.google.appinventor.components.runtime.AndroidNonvisibleComponent;
import com.google.appinventor.components.runtime.ComponentContainer;
import com.google.appinventor.components.runtime.EventDispatcher;

public class Test extends AndroidNonvisibleComponent {

    public Test(ComponentContainer container) {
        super(container.$form());
    }

    @SimpleEvent
    public void AppleFell(int apples) {
        EventDispatcher.dispatchEvent(this, "AppleFell", apples);
    }

    @SimpleEvent
    public void OrangeFell(int oranges) {
        EventDispatcher.dispatchEvent(this, "OrangeFell", oranges);
    }

    @SimpleFunction
    public void GetApples() throws Exception {
        doSomething("...", "AppleFell");
    }

    @SimpleFunction
    public void GetOranges() throws Exception {
        doSomething("....", "OrangeFell");
    }

    private void doSomething(String parameters, String whatEvent) throws Exception {
        int counts = parameters.length();
        // call the event with the name
        // that event has one arg int type
        getClass().getMethod(whatEvent,
                int.class).invoke(this, counts);
    }
}

// second one is event name (any event name in the class)
// but you wont be able to pass method as a paramter
doSomething("....", "OrangeFell");
2 Likes

You might get an idea from dynamic components code it is made upon the principle of reflection :wink:

1 Like

OK, it looks like it will be easier to either:

  1. Follow Taifun's suggestions in using one event, then select the correct event to run
  2. Build an if/else or switch/case statement to select the correct event to run

Thanks to all for your ideas and input, it helped me see the wood from the trees :deciduous_tree:

4 Likes
@SimpleEvent(description = "Event raised when output returned")
  public void GotOutput(final String output, String simpleFunction) {
    EventDispatcher.dispatchEvent(this, "GotOutput", output, simpleFunction);
  }

@SimpleFunction(description = "set parameters to get output")
  public void GetOutput() {
      String parameters = "some parameters";
      GetFunction(parameters);
  }

private void GetFunction(String parameters) {
//do something
//output to event:
GotOutput(output, "mySimpleFunction");
}

Taifun

4 Likes