简体   繁体   中英

Calling Java methods from inner function of GWT JSNI

I'm using W3C Geolocation API in order to retrieve location information within GWT web application. Geolocation API is built the way that callback function gets invoked as soon as location position is retrieved.

My current test code looks as follows:

public native void getCoordinates() /*-{
    function onPositionUpdate(position) {
        var lat = position.coords.latitude;
        var lng = position.coords.longitude;
        var alt = position.coords.altitude;

        // not OK,- doesn't get invoked, and function execution stops at this point
        this.@com.test.GpsPanel::testMethod()();

        alert("Coordinates retrieved: " + lat + ";" + lng + ";" + alt);
    }

    function onPositionUpdateFailed(error) {
        alert("Some error");
    }

    if(navigator.geolocation) {
        // OK when invoked somewhere here
        this.@com.test.GpsPanel::testMethod()();

        navigator.geolocation.getCurrentPosition(onPositionUpdate, onPositionUpdateFailed);
    } else {
        alert("Geolocation is not available");
    }
}-*/;

I'm trying to demonstrate that the method testMethod doesn't get invoked from inner method onPositionUpdate . Even more: no alert is shown afterwards (it does get shown when testMethod call is removed), but no warnings or errors are found in a log.

My question is: how do I reference this method from the inner function? I have feeling that this. is not a correct reference from the inner functions. If Java class cannot be referenced correctly, then what are the possible workarounds? Please note that I cannot pass anything else to function onPositionUpdate() as it's a callback function.

this is out of scope when a function defined within your javascript within the JSNI block is actually executed.

Add a closure around this :

public native void getCoordinates()
/*-{

    var that = this;

    function onPositionUpdate(position) {
        var lat = position.Wecoords.latitude;
        var lng = position.coords.longitude;
        var alt = position.coords.altitude;

        that.@com.test.GpsPanel::testMethod()();

        alert("Coordinates retrieved: " + lat + ";" + lng + ";" + alt);
    }

    // ...
}-*/;

I was sure that this was documented in google's JSNI docs somewhere, at least in a passing example, but I can't find it now.

This can also be accomplished by passing an instance through to the javascript injection, eg:

public native void getCoordinates(com.test.GpsPanel instance)
/*-{

    function onPositionUpdate(position)
    {
        var lat = position.Wecoords.latitude;
        var lng = position.coords.longitude;
        var alt = position.coords.altitude;

        instance.@com.test.GpsPanel::testMethod()();

        alert("Coordinates retrieved: " + lat + ";" + lng + ";" + alt);
    }

    // ...
}-*/;

A related trivial mistake resulting in the same behaviour is to forget the second pair of brackets when invoking Java methods. The first pair restates the method header for identification purposes while the second pair contains the actual argument(s). This mistake is particularly easy to make when there are no arguments, eg

instance.@com.test.GpsPanel::testMethod()();

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