GWT JSNI javascript to Java not working

2019-02-19 16:13发布

I am trying to invoke a Java Method from my Javascript code. This is for a Windows Phone 7 app using Phonegap.

I have the following in my javascript code.

document.addEventListener("backbutton", onBackKeyDown, false);
 function onBackKeyDown(){

    }

And in my Java code I have the following.

  public static native void exportStaticMethod() /*-{
    $wnd.onBackKeyDown = 
        $entry(this.@com.mycompany.myapp.client.MyApp::hideSettingsWidgets());

    }-*/;

Then in the on onModuleLoad() I am calling it like so:

MyApp.exportStaticMethod();

It does not work I have an alert in the hideSettingsWidgets() but it never gets shown.

*EDIT* Here is some more code. The EventListener is not added in the Javascript. It is specifically added withing the java code. I could not get the listeners to register originally so here is what I added.

public static native void removeBackListener() /*-{
   $wnd.removeTheListener();
}-*/;

And in my JavaScript

function removeTheListener(){
        document.removeEventListener("backbutton", onBackKeyDown, false);

        }

Here is my call to hideSettingsWidgets()

public void hideSettingsWidgets(){
        for(int i=0;i<settingsScreenWidgets.length;i++){
            settingsScreenWidgets[i].setVisible(false);
        }
        alertString("Working");
        removeBackListener();



    }

And I am calling the method you gave me inside showSettingsWidgets()

p

rivate void showSettingsWidgets(){
        for(int i=0;i<settingsScreenWidgets.length;i++){
            settingsScreenWidgets[i].setVisible(true);
        }
        setCurrentImage();
        setOnOffImage();
        setupJavaHandler();

    }

It does seem to be adding the EventListener that is inside your

public native void setupJavaHandler() /*-{
      var app = this;
      var onBackKeyDown = $entry(function() {
        app.@com.mycompany.myapp.client.MyApp::hideSettingsWidgets();
      });
      $doc.addEventListener("backbutton", onBackKeyDown, false);
    }-*/;

So I am not sure where I am going wrong. I did not add the ArrayList<> you mentioned because was not sure to and the Event Listener was not running when page was Loaded.

Seems like showSettingsWidgets() never gets run

标签: gwt jsni
1条回答
【Aperson】
2楼-- · 2019-02-19 16:45

The addEventListener code is probably running when the page loads, right? This will map your empty function onBackKeyDown to the backbutton event. Then, when your module loads, you attempt to redefine the onBackKeyDown function to be a new one - but the old one was already attached to the event you are trying to listen to.

This is roughly the equivalent of this (with strings instead of listener functions):

// first, make the thing to hold the 'listener', and define the first one
List<String> strings = new ArrayList<String>();
String onBackKeyDown = "abcd";
strings.add(onBackKeyDown);

// then, redefine the string, but don't change the list!
onBackKeyDown = "zyxw";

assert strings.contains(onBackKeyDown) : "Whoops, reassigned, but not added!";

To fix this, you need a cross between what you are doing in your other question, Adding Eventlisteners to document with GWT JSNI, and what you are doing here. Wrapping the Java function in an $entry call, and passing that to $doc.addEventListener makes the most logical sense (though I don't know a lot about WP7).

public static native void setupJavaHandler() /*-{
  var onBackKeyDown = $entry(this.@com.mycompany.myapp.client.MyApp::hideSettingsWidgets());
  $doc.addEventListener("backbutton", onBackKeyDown, false);
}-*/;

One more thing - remembering that we are writing JavaScript in that native code, what is going to be this when that hideSettingsWidgets() method is called? JavaScript doesn't know that all Java instance methods need a this to run on (and JavaScript has no problem running methods for object A on B - A.method.call(B) is totally legal, and often helpful). We need to be sure that this means what we think it does:

public static native void setupJavaHandler() /*-{
  var app = this;
  var onBackKeyDown = $entry(function() {
    app.@com.mycompany.myapp.client.MyApp::hideSettingsWidgets();
  });
  $doc.addEventListener("backbutton", onBackKeyDown, false);
}-*/;

Edit: Oops, turns out your method was static anyway, so this doesn't actually mean anything! Either change exportStaticMethod/setupJavaHandler to be non static and call it directly (probably in your onModuleLoad as you have it now), or pass in an instance to call hideSettingsWidgets() on, like we are doing with app in the previous sample.

public native void setupJavaHandler() /*-{
  var app = this;
  var onBackKeyDown = $entry(function() {
    app.@com.mycompany.myapp.client.MyApp::hideSettingsWidgets();
  });
  $doc.addEventListener("backbutton", onBackKeyDown, false);
}-*/;
// in onModuleLoad:
setupJavaHandler();

or

public static native void setupJavaHandler(MpApp app) /*-{
  //var app = this;
  var onBackKeyDown = $entry(function() {
    app.@com.mycompany.myapp.client.MyApp::hideSettingsWidgets();
  });
  $doc.addEventListener("backbutton", onBackKeyDown, false);
}-*/;

// in onModuleLoad:
MyApp.setupJavaHandler(this);
查看更多
登录 后发表回答